<- back

advent of code - day 3

2023-12-03

See the puzzle here.

See my full solution here.

Part 1

With my implementation at least, this one boiled down to loading the input into a giant matrix, and iterating over it to find which numbers are adjacent to symbols, and which aren't. Not too many tricks here, just "can you keep track of this matrix correctly".

I created a helper function to determine if a character should be considered a "symbol" or not:

const isSymbol = (char) => {
 return !/[0-9|.]/.test(char);
}

From there, it's just a amtter of looking above, to the side, and below each number to check if there's a symbol or not. For example:

if(i > 0) {
 if(j > 0) {
  if(isSymbol(input[i-1][j-1])) {
   isPart = true;
  }
 }
 if(isSymbol(input[i-1][j])) {
  isPart = true;
 }
 if(j < input[i].length-1) {
  if(isSymbol(input[i-1][j+1])) {
   isPart = true;
  }
 }
}

Once you find a number that is considered a part, just add it to the overall answer.

Part 2

Not too big of a twist for part 2. This time we need to find * symbols that are adjacent to exactly two numbers, multiply those numbers, and total them up.

To me the biggest "trick" here was to figure out the full number when you see an adjacent digit. You can't just see two digits that are adjacent to an * and say it's a gear. They might be part of the same number. So I created the following function to find the whole number the digit is a part of:

const figureOutNumber = (i, j) => {
 let numberStr = '';
 let firstIndex = 0;
 for(let k=j; k>-1; k--) {
  if(/[0-9]/.test(input[i][k])) {
   firstIndex = k;
  } else {
   break;
  }
 }
 for(let k=firstIndex; k   if(!/[0-9]/.test(input[i][k])) {
   break;
  }
  numberStr += input[i][k];
 }
 return parseInt(numberStr);
}

Using that function, I just look for digits that surroung each * symbol, run that digit through the function, and avoid double counting the same number twice.