Advent Of Code Day 3

Day 3: Gear Ratios

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

On day 3, we’re given an “engine schematic”:

467..114..
...*......
..35..633.
......#...
617*......
.....+.58.
..592.....
......755.
...$.*....
.664.598..

For part 1, sum the numbers adjacent to a symbol (excluding dots).

Many possible options. Here’s one:

data←↑⊃⎕NGET'3'1
digits←data∊⎕D
dd←digits+({((5⊃,⍵)∊⎕D)∧(0<≢(,⍵)~' .0123456789')})⌺3 3⊢data
+/⍎¨(digits⊆⍤1 1⊢data)[⍸2∊¨digits⊆⍤1 1⊢dd]

Nothing too clever. For part 2, we’re asked to locate ‘gears’, defined as being two numbers (no more, no fewer) adjacent to the same symbol *. This is a bit harder. Here’s an annotated solution, adapted from one written by Aaron Hsu:

part2 ← { ⍝ Based on a solution from Aaron Hsu
    ⍝ Id all *s by their ravel index
    sh ← ⍴⍵
    stars ← sh⍴(⍳×/sh)×,'*'=⍵
    
    ⍝ Fill each *'s 3×3 neighbourhood with its id.
    catchment ← {⌈/⌈/⍵}⌺3 3⊢stars

    ⍝ Generate a mask showing the location of the numbers
    digits ← ⍵∊⎕D
    
    ⍝ .. and use this to extract the numbers in ravel order.
    numbers ← ⍎¨digits⊆⍥,⍵

    ⍝ We can use the digits mask to grab from the gear
    ⍝ catchment areas in the same way. We pick the max 
    ⍝ as we don't care if several digits of the same number
    ⍝ may fall within the same catchment area.
    gears ← ⌈/¨digits⊆⍥,catchment

    ⍝ In order to qualify, a gear must have exactly two numbers
    ⍝ in its catchment area
    +/{2=≢⍵:×/numbers[⍵]⋄0}⌸gears
}

‘Tagging’ a Boolean mask with the corrsponding ravel index is something likely to be useful for other problems:

stars ← sh⍴(⍳×/sh)×,'*'=⍵

The problems are definitely harder this year, perhaps in an attempt to confuse LLMs.

Written on December 5, 2023