Day 3

prelude

https://adventofcode.com/2024/day/3

import { inputDay } from "./lib/utilities.js"

The munge function I wrote in 01 - utilities is not useful for today, so I updated the inputDay function to accept a parser parameter that lets us pass a parser to it.

part 1

To pull out mul(x,y) statements, we can use a regular expression mul\((\d+),(\d+)\). Thankfully, there aren't any spaces or negative numbers to deal with, so we can keep it simple.

On the test input, pull out each mul instruction, parse the arguments into numbers, multiply them, and sum the result.

const test = `xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))`
const product = test
  .matchAll(/mul\((\d+),(\d+)\)/g)
  .map(([, a, b]) => a * b)
  .reduce((a, b) => a + b)
display(product)

To understand that code, it's important to know that + as a unary operator will convert a string to a number:

display(+"12")
display(+"-42")

Our test code produced the correct result, so let's turn it into a function

function parser(input) {
  return input
    .matchAll(/mul\((\d+),(\d+)\)/g)
    .map(([, a, b]) => +a * +b)
    .reduce((a, b) => a + b)
}

Which we can then use to parse the input

display(await inputDay(3, { parser }))

part 2

Now we need to add do\(\) and don't\(\) as options to our regular expression; we can use the alternation operator | and stick them on the end.

If the match has two groups, we'll multiply it as before; otherwise, just return the match.

function parser2(input) {
  return input
    .matchAll(/mul\((\d+),(\d+)\)|do\(\)|don't\(\)/g)
    .map(([match, a, b]) => (b ? +a * +b : match))
}

The result is an iterator which will return either a number, or a literal do() or don't()

const instructions = (await inputDay(3, { parser: parser2 })).toArray()
display(instructions)

Go through the list and sum up the numbers when active is true

let active = true
let sum = 0
for (const instr of instructions) {
  if (active && typeof instr == "number") sum += instr
  if (active && instr == "don't()") active = false
  if (!active && instr == "do()") active = true
}
display(sum)