ShareMyScreen/AdventOfCode/2023/03/GearRatios/rdm
1sample=: {{)n
2467..114..
3...*......
4..35..633.
5......#...
6617*......
7.....+.58.
8..592.....
9......755.
10...$.*....
11.664.598..
12}}
13day3=: fread '2023-day3.txt'
14
15digits=:'0123456789'
Here, we had numbers and symbols, and we needed to sum the numbers which were touched (in any direction) by a symbol (any non-numeric character other than '.')
I plodded through this, breaking up the input into lines (and leaving the linefeed in each line for reasons I'll explain in a moment - but making sure to mark linefeeds as "not a symbol".
Next, I generated a bit matrix which represented the characters touched by each symbol, and I also located the start of each number in the initial argument. (This is why I left the linefeeds in place - so that each position in my matrices would match up with the same position in the raw argument.)
A running scan of the bits marking the number starts gives each number a unique id number (1, 2, 3, 4), .. let's dive into the code for a moment, with globals assigned to make it easy to inspect intermediate results:
17part1=: {{
18 chmat=: ];.2 y
19 symbol=: chmat e. a.-.'.',digits,LF
20 touched=: ,+./(_1 0 1)|."0 2 +./(_1 0 1)|."0 1/ symbol
21 numeric=: ,chmat e. digits
22 segments=: }:0 1 E.0,numeric
23 keep=: <:}.~.0,touched#numeric*+/\segments
24 numbers=: segments ".@([-.-.)&digits;.1,chmat
25 +/keep{numbers
26}}
part1 sample
4361
($symbol)$touched
0 0 1 1 1 0 0 0 0 0 0
0 0 1 1 1 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0 0
0 0 1 1 1 1 1 1 0 0 0
0 0 1 1 1 1 1 1 0 0 0
0 0 1 1 1 1 1 0 0 0 0
0 0 0 0 1 1 1 0 0 0 0
0 0 1 1 1 1 1 0 0 0 0
0 0 1 1 1 1 1 0 0 0 0
0 0 1 1 1 1 1 0 0 0 0
($symbol)$numeric*+/\segments
1 1 1 0 0 2 2 2 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 3 3 0 0 4 4 4 0 0
0 0 0 0 0 0 0 0 0 0 0
5 5 5 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 6 6 0 0
0 0 7 7 7 0 0 0 0 0 0
0 0 0 0 0 0 8 8 8 0 0
0 0 0 0 0 0 0 0 0 0 0
0 9 9 9 0 10 10 10 0 0 0
As you can see, each number that is adjacent to a symbol has a non-zero id here in this intermediate result. The unique values here (after discarding zeros) correspond to indices into the list of represented numbers.
For part 2, I wanted the product of pairs of numbers which were adjacent to asterisks. Here, I brute forced it and paired the ids adjacent to every place in the matrix and then selected those which corresponded to asterisks.
28part2=: {{
29 sh=: $chmat=: ];.2 y
30 asterisk=: I.,chmat e. '*'
31 numeric=: chmat e. digits
32 segments=: sh$0 1 E.0,,numeric
33 numbers=: (,segments) ".@([-.-.)&digits;.1,chmat
34 ids=: sh$(,numeric)*+/\,segments
35 adjacent=: ~.@,each/_1 0 1|."0 2~.@,each/_1 0 1|."0 1/ids
36 pairs=: <:>(#~ 2=#@>)asterisk{,adjacent -.each 0
37 +/*/|:pairs{numbers
38}}
It turns out that there were never more than 2 numbers next to an asterisk. At the very least, that means I could have eliminated the (#~ 2=#@>)
from the result. It also probably would have made more sense to only locate ids adjacent to asterisks rather than everywhere.