Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- clc
- clear
- close all
- tic
- disp('starting...')
- x = importdata('input.txt');
- s = x{1};
- for i=2:size(x,1)
- s = addSnailfishNumbers(s,x{i});
- end
- M = getMagnitude(s);
- disp(M);
- % Part 2
- maxM = -inf;
- for i=1:size(x,1)
- for j=1:size(x,1)
- s = addSnailfishNumbers(x{i},x{j});
- M = getMagnitude(s);
- if M>maxM
- maxM=M;
- end
- end
- end
- disp(maxM)
- toc
- disp('Finished')
- function s = addSnailfishNumbers(x,y)
- s = ['[',x,',',y,']'];
- s = reduceSnailfishNumber(s);
- end
- function y = reduceSnailfishNumber(s)
- while 1
- sNew = explodeSnailfishNumber(s);
- if isequal(sNew,s)
- sNew = splitSnailfishNumber(s);
- if isequal(sNew,s)
- break
- end
- s = sNew;
- end
- s = sNew;
- end
- y=s;
- end
- function y=explodeSnailfishNumber(s)
- L = getSnailfishNumberLevel(s);
- if ~any(L==4) % nothing to explode, return the orginal number
- y=s;
- return
- end
- % Find positions of leftmost pair to explode
- idxList = find(L==4);
- startIdx = idxList(1);
- z = find(diff(idxList)~=1, 1);
- if isempty(z)
- endIdx = idxList(end);
- else
- endIdx = idxList(z(1));
- end
- pairToExplode = s(startIdx:endIdx);
- %% find the first number to the left of the pair to explode (if any);
- leftNumberStr = [];
- for i = startIdx-1:-1:1
- if s(i)>47 && s(i)<58 % 0..9
- leftNumberStr = s(i);
- leftNumberEndIdx = i;
- for j=i-1:-1:1
- if s(j)>47 && s(j)<58 % 0..9
- leftNumberStr = [s(j),leftNumberStr];
- else
- leftNumberStartIdx = j+1;
- break
- end
- end
- break
- end
- end
- if ~isempty(leftNumberStr)
- leftNumberVal = str2double(leftNumberStr);
- end
- %% find the first number to the right of the pair to explode (if any);
- rightNumberStr = [];
- for i = endIdx+1:length(s)
- if s(i)>47 && s(i)<58 % 0..9
- rightNumberStr = s(i);
- rightNumberStartIdx = i;
- for j=i+1:length(s)
- if s(j)>47 && s(j)<58 % 0..9
- rightNumberStr = [rightNumberStr,s(j)];
- else
- rightNumberEndIdx = j-1;
- break
- end
- end
- break
- end
- end
- if ~isempty(rightNumberStr)
- rightNumberVal = str2double(rightNumberStr);
- end
- %% Modify left/right numbers
- pairValues = getPairValues(pairToExplode);
- if ~isempty(rightNumberStr)
- % Add right value of exploded pair to the first number right of it:
- newRightVal = rightNumberVal + pairValues(2);
- newRightStr = num2str(newRightVal);
- s = [s(1:rightNumberStartIdx-1),newRightStr,s(rightNumberEndIdx+1:end)];
- end
- % replace exploding pair with '0'
- s = [s(1:startIdx-1),'0',s(endIdx+1:end)];
- if ~isempty(leftNumberStr)
- % Add left value of exploded pair the the first number left of it:
- newLeftVal = leftNumberVal + pairValues(1);
- newLeftStr = num2str(newLeftVal);
- s = [s(1:leftNumberStartIdx-1),newLeftStr,s(leftNumberEndIdx+1:end)];
- end
- y=s;
- end
- function s = splitSnailfishNumber(s)
- % find numbers > 9 and split the leftmost of those numbers.
- idxZeroToNine = s>47 & s<58;
- idxLargerThanNine = strfind(idxZeroToNine,[1,1]); % i.e. at least 2 characters from 0-9 in a row.
- if isempty(idxLargerThanNine)
- return %nothing to split
- else
- splitNumberStartIdx = idxLargerThanNine(1);
- end
- splitNumberStr = s(splitNumberStartIdx);
- for k=splitNumberStartIdx+1:length(s)
- if s(k)>47 && s(k)<58
- splitNumberStr = [splitNumberStr,s(k)];
- else
- splitNumberEndIdx = k-1;
- break
- end
- end
- splitNumberVal = str2double(splitNumberStr);
- splitNumberVal1 = floor(splitNumberVal/2);
- splitNumberVal2 = ceil(splitNumberVal/2);
- splitNumberVal1Str = num2str(splitNumberVal1);
- splitNumberVal2Str = num2str(splitNumberVal2);
- replacementPair = ['[',splitNumberVal1Str,',',splitNumberVal2Str,']'];
- s = [s(1:splitNumberStartIdx-1),replacementPair,s(splitNumberEndIdx+1:end)];
- end
- function L=getSnailfishNumberLevel(s)
- L = zeros(1,size(s,2));
- currentLevel = -1;
- for i=1:size(s,2)
- switch s(i)
- case '['
- currentLevel = currentLevel + 1;
- L(i) = currentLevel;
- case ']'
- L(i) = currentLevel;
- currentLevel = currentLevel - 1;
- otherwise
- L(i) = currentLevel;
- end
- end
- end
- function val = getPairValues(p)
- val = [str2double(p(2:find(p==',')-1)),str2double(p(find(p==',')+1:end-1))];
- end
- function M = getMagnitude(s)
- while 1
- L = getSnailfishNumberLevel(s);
- maxDepth = max(L);
- idxMaxDepth = find(L==maxDepth);
- startIdx = idxMaxDepth(1);
- z = find(diff(idxMaxDepth)~=1);
- if isempty(z)
- endIdx = idxMaxDepth(end);
- else
- endIdx = idxMaxDepth(z(1));
- end
- val = str2num(s(startIdx:endIdx)); %#ok<ST2NM>
- newVal = 3*val(1) + 2*val(2);
- newValStr = num2str(newVal);
- s = [s(1:startIdx-1),newValStr,s(endIdx+1:end)];
- if maxDepth==0
- break
- end
- end
- M=str2double(s);
- end
Advertisement
Add Comment
Please, Sign In to add comment