Skip to content

2023 - Day 1 - Trebuchet?!

Posted on:December 1, 2023 at 08:30 AM

Elves’ Calibration Conundrum

The new year of Advent of Code begins with a numeric puzzle: a calibration document altered by an enthusiastic young elf. Our goal? To decipher calibration values hidden within lines of text and calculate their sum.

Our Solution

We approach this challenge leveraging regular expressions and string manipulation to extract and compute the necessary calibration values.

Part One: Extracting Numbers

export default function partOne(inputArray: string[]): number {
  return inputArray
    .map(line => {
      const match = line.match(/\d/g);
      return match ? parseInt(match[0] + match[match.length - 1]) : 0;
    })
    .reduce((a, b) => a + b, 0);
}

In part one, we extract the first and last digits from each line using regular expressions. Then, we form a two-digit number and sum these numbers across all lines.

Part Two: Decoding Numeric Words

const numbers: Record<string, string> = {
  one: "1",
  two: "2",
  three: "3",
  four: "4",
  five: "5",
  six: "6",
  seven: "7",
  eight: "8",
  nine: "9",
};

function findWords(input: string) {
  const words = [...Object.keys(numbers), ...Object.values(numbers)];
  const matches = [];

  for (const word of words) {
    let pos = input.indexOf(word);
    while (pos !== -1) {
      matches.push({ word, pos });
      pos = input.indexOf(word, pos + 1);
    }
  }

  return matches.sort((a, b) => a.pos - b.pos);
}

export default function partTwo(inputArray: string[]): number {
  return inputArray
    .map(line => {
      const words = findWords(line);
      if (!words.length) return 0;

      const firstWord = words[0].word;
      const first = numbers[firstWord] || firstWord;

      const lastWord = words[words.length - 1].word;
      const last = numbers[lastWord] || lastWord;

      return parseInt(first + last);
    })
    .reduce((a, b) => a + b, 0);
}

For part two, we adjust our strategy to account for numeric words. Using a lookup table for digit words (like ‘one’, ‘two’, etc.), we find and convert these words to their corresponding digits, then proceed as in part one.

Tackling Overlapping Numbers

In partTwo of our puzzle, we encountered an intriguing challenge: dealing with strings that contained overlapping numeric representations. For example, a string like “1fiveight” includes the digit ‘1’, the word ‘five’, and the word ‘eight’. This complexity made it impractical to use regular expressions (regex) directly for extracting numbers.

Our Approach

To address these challenges, we used a more manual but reliable approach:

  1. Creating a Words Array: We prepared an array with all possible numeric representations - both as digits and words.
  2. Finding Words: We looped through this array to find occurrences of each representation in the input string. This approach ensured that we didn’t miss any overlapping numbers.
  3. Sorting by Position: After finding all matches, we sorted them by their position in the string. This was crucial for identifying the first and last numeric representation accurately.
  4. Calculating the Sum: Finally, we converted these representations to their numeric values and summed them up as required by the puzzle.

Conclusion

This challenge was a delightful mix of string manipulation and numeric conversion. It was a creative start to this year’s Advent of Code, blending problem-solving with a touch of whimsy.