<- back

advent of code - day 1

2023-12-01

See the puzzle here.

See my full solution here.

It could just be that I was doing it while simultaneously watching my kids, but I thought this year's day 1 was a bit harder than last years.

When I'm doing these advent of code problems, I am much more focused on quickly getting the right answer than anything else, so my solution is not very pretty, but it gets the job done.

Part 1

This part was pretty straightforward. Here's the main chunk of code that runs on each line of input:

 let numberStr = '';
 let number = 0;
 for(let i=0; i   const char = line.charAt(i);
  if(/^\d+$/.test(char)) {
   numberStr += `${char}`;
   break;
  }
 }
 for(let i=line.length-1; i>-1; i--) {
  const char = line.charAt(i);
  if(/^\d+$/.test(char)) {
   numberStr += `${char}`;
   break;
  }
 }
 number = parseInt(numberStr);
 sum += number;

Basically, my strategy was to loop over the string and find the first number by testing against a regex, then loop over the string backwards and find the last number. Then I just jam those two numbers together and parse it as an integer.

Part 2

Right off the bat this seemed pretty tricky. Here's my (gross) code that runs on each line of input:

 const words = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
 let numberStr = '';
 let number = 0;

 let firstWordIndex = 9999999;
 let lastWordIndex = -1;
 let firstWord = '';
 let firstDigitIndex = 9999999;
 let lastDigitIndex = -1;
 let lastWord = '';


 for(let i=0; i   const word = words[i];
  if(line.indexOf(word) > -1) {
   if(line.indexOf(word) < firstWordIndex) {
    firstWordIndex = line.indexOf(word);
    firstWord = word;
   }
  }
 }
 for(let i=0; i   const word = words[i];
  if(line.lastIndexOf(word) > -1) {
   if(line.lastIndexOf(word) > lastWordIndex && line.lastIndexOf(word) !== firstWordIndex) {
    lastWordIndex = line.lastIndexOf(word);
    lastWord = word;
   }
  }
 }

 for(let i=0; i   const char = line.charAt(i);
  if(/^\d+$/.test(char)) {
   firstDigitIndex = i;
   break;
  }
 }
 for(let i=line.length-1; i>-1; i--) {
  const char = line.charAt(i);
  if(/^\d+$/.test(char)) {
   lastDigitIndex = i;
   break;
  }
 }

 if(firstWordIndex === 9999999 && lastWordIndex !== -1) {
  firstWordIndex = lastWordIndex;
  firstWord = lastWord;
 }

 if(lastWordIndex === -1 && firstWordIndex !== 9999999) {
  lastWordIndex = firstWordIndex;
  lastWord = firstWord;
 }

 if(firstDigitIndex === 9999999 && lastDigitIndex !== -1) {
  firstDigitIndex = lastDigitIndex;
 }

 if(lastDigitIndex === -1 && firstDigitIndex !== 9999999) {
  lastDigitIndex = firstDigitIndex;
 }

 if(firstDigitIndex < firstWordIndex || firstWordIndex === 9999999) {
  numberStr += `${line.charAt(firstDigitIndex)}`;
 } else {
  numberStr += `${words.indexOf(firstWord)}`;
 }

 if(lastDigitIndex > lastWordIndex || lastWordIndex === -1) {
  numberStr += `${line.charAt(lastDigitIndex)}`;
 } else {
  numberStr += `${words.indexOf(lastWord)}`;
 }

 number = parseInt(numberStr);
 sum += number;

Immediately I knew I needed to make an array that contains all of the possible digits as words: "zero", "one", so on.

The first thing that happens is I loop over the possible "number words" to find the first and last occurence of them in the line.

Next, I use the same approach as in the previous part to find the first and last digits in the line.

The next part is the tricky bit. This is where we need to use these detected words and digits to figure out which ones to jam together to form the final number we need to add to the total sum. Especially tricky: we need to handle the cases where there are no digits, no words, or only one word or digit. Basically, I check "was no first word detected and a last word was detected? I'll use the last as the first", "was no last word detected and a first word was detected? I'll use the first as the last", and so on. Then I just check what comes first, a word or a digit? And I use that as the first digit in the final number. Then I check what comes last, a word or a digit? And I use that as the last digit in the final number.