Guest User

Dag 18 in MATLAB

a guest
Dec 18th, 2021
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
MatLab 5.14 KB | None | 0 0
  1. clc
  2. clear
  3. close all
  4.  
  5. tic
  6. disp('starting...')
  7.  
  8. x = importdata('input.txt');
  9. s = x{1};
  10. for i=2:size(x,1)
  11.     s = addSnailfishNumbers(s,x{i});
  12. end
  13. M = getMagnitude(s);
  14. disp(M);
  15.  
  16. % Part 2
  17. maxM = -inf;
  18. for i=1:size(x,1)
  19.     for j=1:size(x,1)
  20.         s = addSnailfishNumbers(x{i},x{j});
  21.         M = getMagnitude(s);
  22.         if M>maxM
  23.             maxM=M;
  24.         end
  25.     end
  26. end
  27. disp(maxM)
  28. toc
  29. disp('Finished')
  30.  
  31. function s = addSnailfishNumbers(x,y)
  32. s = ['[',x,',',y,']'];
  33. s = reduceSnailfishNumber(s);
  34. end
  35.  
  36. function y = reduceSnailfishNumber(s)
  37. while 1
  38.     sNew = explodeSnailfishNumber(s);
  39.     if isequal(sNew,s)
  40.         sNew = splitSnailfishNumber(s);
  41.         if isequal(sNew,s)
  42.             break
  43.         end
  44.         s = sNew;
  45.     end
  46.     s = sNew;
  47. end
  48. y=s;
  49. end
  50.  
  51. function y=explodeSnailfishNumber(s)
  52. L = getSnailfishNumberLevel(s);
  53.  
  54. if ~any(L==4) % nothing to explode, return the orginal number
  55.     y=s;
  56.     return
  57. end
  58.  
  59. % Find positions of leftmost pair to explode
  60. idxList     = find(L==4);
  61. startIdx    = idxList(1);
  62.  
  63. z = find(diff(idxList)~=1, 1);
  64. if isempty(z)
  65.     endIdx = idxList(end);
  66. else
  67.     endIdx = idxList(z(1));
  68. end
  69.  
  70. pairToExplode = s(startIdx:endIdx);
  71.  
  72. %% find the first number to the left of the pair to explode (if any);
  73. leftNumberStr = [];
  74. for i = startIdx-1:-1:1
  75.     if s(i)>47 && s(i)<58 % 0..9
  76.         leftNumberStr = s(i);
  77.         leftNumberEndIdx = i;
  78.         for j=i-1:-1:1
  79.             if s(j)>47 && s(j)<58 % 0..9
  80.                 leftNumberStr = [s(j),leftNumberStr];
  81.             else
  82.                 leftNumberStartIdx = j+1;
  83.                 break
  84.             end
  85.         end
  86.         break
  87.     end
  88. end
  89. if ~isempty(leftNumberStr)
  90.     leftNumberVal = str2double(leftNumberStr);
  91. end
  92. %% find the first number to the right of the pair to explode (if any);
  93. rightNumberStr = [];
  94. for i = endIdx+1:length(s)
  95.     if s(i)>47 && s(i)<58 % 0..9
  96.         rightNumberStr = s(i);
  97.         rightNumberStartIdx = i;
  98.         for j=i+1:length(s)
  99.             if s(j)>47 && s(j)<58 % 0..9
  100.                 rightNumberStr = [rightNumberStr,s(j)];
  101.             else
  102.                 rightNumberEndIdx = j-1;
  103.                 break
  104.             end
  105.         end
  106.         break
  107.     end
  108. end
  109. if ~isempty(rightNumberStr)
  110.     rightNumberVal = str2double(rightNumberStr);
  111. end
  112.  
  113. %% Modify left/right numbers
  114. pairValues = getPairValues(pairToExplode);
  115.  
  116. if ~isempty(rightNumberStr)
  117.    % Add right value of exploded pair to the first number right of it:
  118.    newRightVal = rightNumberVal + pairValues(2);
  119.    newRightStr = num2str(newRightVal);
  120.    s = [s(1:rightNumberStartIdx-1),newRightStr,s(rightNumberEndIdx+1:end)];
  121. end
  122.  
  123. % replace exploding pair with '0'
  124. s = [s(1:startIdx-1),'0',s(endIdx+1:end)];
  125.  
  126. if ~isempty(leftNumberStr)
  127.    % Add left value of exploded pair the the first number left of it:
  128.    newLeftVal = leftNumberVal + pairValues(1);
  129.    newLeftStr = num2str(newLeftVal);
  130.    s = [s(1:leftNumberStartIdx-1),newLeftStr,s(leftNumberEndIdx+1:end)];
  131. end
  132. y=s;
  133. end
  134.  
  135. function s = splitSnailfishNumber(s)
  136. % find numbers > 9 and split the leftmost of those numbers.
  137. idxZeroToNine       = s>47 & s<58;
  138. idxLargerThanNine   = strfind(idxZeroToNine,[1,1]); % i.e. at least 2 characters from 0-9 in a row.
  139.  
  140. if isempty(idxLargerThanNine)
  141.     return %nothing to  split
  142. else
  143.     splitNumberStartIdx = idxLargerThanNine(1);
  144. end
  145.  
  146. splitNumberStr = s(splitNumberStartIdx);
  147. for k=splitNumberStartIdx+1:length(s)
  148.     if s(k)>47 && s(k)<58
  149.         splitNumberStr = [splitNumberStr,s(k)];    
  150.     else
  151.         splitNumberEndIdx = k-1;
  152.         break
  153.     end
  154. end
  155.  
  156. splitNumberVal      = str2double(splitNumberStr);
  157. splitNumberVal1     = floor(splitNumberVal/2);
  158. splitNumberVal2     = ceil(splitNumberVal/2);
  159.  
  160. splitNumberVal1Str  = num2str(splitNumberVal1);
  161. splitNumberVal2Str  = num2str(splitNumberVal2);
  162.  
  163. replacementPair     = ['[',splitNumberVal1Str,',',splitNumberVal2Str,']'];
  164. s = [s(1:splitNumberStartIdx-1),replacementPair,s(splitNumberEndIdx+1:end)];
  165. end
  166.  
  167. function L=getSnailfishNumberLevel(s)
  168. L = zeros(1,size(s,2));
  169. currentLevel = -1;
  170. for i=1:size(s,2)
  171.     switch s(i)
  172.         case '['
  173.             currentLevel    = currentLevel + 1;
  174.             L(i)            = currentLevel;
  175.         case ']'
  176.             L(i)            = currentLevel;
  177.             currentLevel    = currentLevel - 1;
  178.         otherwise
  179.             L(i)            = currentLevel;
  180.     end
  181. end
  182. end
  183.  
  184. function val = getPairValues(p)
  185. val = [str2double(p(2:find(p==',')-1)),str2double(p(find(p==',')+1:end-1))];
  186. end
  187.  
  188. function M = getMagnitude(s)
  189. while 1
  190.     L           = getSnailfishNumberLevel(s);
  191.     maxDepth    = max(L);
  192.     idxMaxDepth = find(L==maxDepth);
  193.     startIdx    = idxMaxDepth(1);
  194.    
  195.     z           = find(diff(idxMaxDepth)~=1);
  196.     if isempty(z)
  197.         endIdx = idxMaxDepth(end);
  198.     else
  199.         endIdx = idxMaxDepth(z(1));
  200.     end
  201.    
  202.     val         = str2num(s(startIdx:endIdx)); %#ok<ST2NM>
  203.     newVal      = 3*val(1) + 2*val(2);
  204.     newValStr   = num2str(newVal);
  205.     s           = [s(1:startIdx-1),newValStr,s(endIdx+1:end)];
  206.     if maxDepth==0
  207.         break
  208.     end
  209. end
  210. M=str2double(s);
  211. end
Advertisement
Add Comment
Please, Sign In to add comment