Hung-Yi's LogoHung-Yi’s Journal

Advent of Code 2022: Day 2

A TypeScript solution for the Advent of Code 2022, Day 2 puzzle: taking advantage of combinations and lookup tables.

Today’s puzzle encodes a strategy for rock, paper scissors into moves that are represented by pairs of characters. We’re asked to score the strategy based on different interpretations of what the characters mean and by following a simple scoring system based on the play (i.e. rock = 1, paper = 2, scissors = 3) and outcome (i.e. win = 6, draw = 3, lose = 0).

The key insight for a simple solution is that there are only 9 different combinations of moves in any given strategy1, and each combination has a fixed score. Instead of being clever with code, we can just work out the 9 different possible scores and put them in a lookup table.

The puzzle input (a.k.a. strategy) looks something like this.

A Y
B X
C Z

First we split the strategy into moves, as each line represents one move.

const strategy: string[] = puzzleInput.split('\n');

Then we make a reducer factory that takes a list of 9 lookup entries, generates a lookup table (i.e. Map<string, number>) which translates any of the 9 possible moves into scores and totals them up.

const scoreReducer = (lookup: [string, number][]) => {
  const lookupTable = new Map<string, number>(lookup);
  return (sum: number, move: string) =>
    sum + lookupTable.get(move)
}

For part 1, X, Y and Z mean our move should be rock, paper or scissors respectively, so determine the outcome and calculate the scores for the 9 different moves and reduce the strategy to get the final score.

const part1 = strategy.reduce(scoreReducer([
  ['A X', 1 + 3], // rock -> rock + draw
  ['A Y', 2 + 6], // rock -> paper + win
  ['A Z', 3 + 0], // rock -> scissors + lose
  ['B X', 1 + 0], // paper -> rock + lose
  ['B Y', 2 + 3], // paper -> paper + draw
  ['B Z', 3 + 6], // paper -> scissors + win
  ['C X', 1 + 6], // scissors -> rock + win
  ['C Y', 2 + 0], // scissors -> paper + lose
  ['C Z', 3 + 3], // scissors -> scissors + draw
]), 0);

For part 2, X, Y and Z mean we should lose, draw or win respectively, so infer our move based on the desired outcome, then score the 9 different combos and reduce the strategy again.

const part2 = strategy.reduce(scoreReducer([
  ['A X', 0 + 3], // rock -> lose + scissors
  ['A Y', 3 + 1], // rock -> draw + rock
  ['A Z', 6 + 2], // rock -> win + paper
  ['B X', 0 + 1], // paper -> lose + rock
  ['B Y', 3 + 2], // paper -> draw + paper
  ['B Z', 6 + 3], // paper -> win + scissors
  ['C X', 0 + 2], // scissors -> lose + paper
  ['C Y', 3 + 3], // scissors -> draw + scissors
  ['C Z', 6 + 1], // scissors -> win + rock
]), 0);

Final Solution

const strategy: string[] = puzzleInput.split('\n');

const scoreReducer = (lookup: [string, number][]) => {
  const lookupTable = new Map<string, number>(lookup);
  return (sum: number, move: string) =>
    sum + lookupTable.get(move)
}

const part1 = strategy.reduce(scoreReducer([
  ['A X', 1 + 3], // rock -> rock + draw
  ['A Y', 2 + 6], // rock -> paper + win
  ['A Z', 3 + 0], // rock -> scissors + lose
  ['B X', 1 + 0], // paper -> rock + lose
  ['B Y', 2 + 3], // paper -> paper + draw
  ['B Z', 3 + 6], // paper -> scissors + win
  ['C X', 1 + 6], // scissors -> rock + win
  ['C Y', 2 + 0], // scissors -> paper + lose
  ['C Z', 3 + 3], // scissors -> scissors + draw
]), 0);

const part2 = strategy.reduce(scoreReducer([
  ['A X', 0 + 3], // rock -> lose + scissors
  ['A Y', 3 + 1], // rock -> draw + rock
  ['A Z', 6 + 2], // rock -> win + paper
  ['B X', 0 + 1], // paper -> lose + rock
  ['B Y', 3 + 2], // paper -> draw + paper
  ['B Z', 6 + 3], // paper -> win + scissors
  ['C X', 0 + 2], // scissors -> lose + paper
  ['C Y', 3 + 3], // scissors -> draw + scissors
  ['C Z', 6 + 1], // scissors -> win + rock
]), 0);

console.log("Part 1:", part1);
console.log("Part 2:", part2);
Part 1: 12156
Part 2: 10835

Footnotes:

1

For the opponent’s move, we can choose from 3 options (A, B or C) and for our move we can also choose from 3 options (X, Y or Z). 3 ✕ 3 = 9.