ShareMyScreen/AdventOfCode/2022/09/RopeBridge
Another simulation problem. The inputs are well-formed J, so I'll just write a verb for each action. First to read in the data:
]lines =: < onaoclines +---+---+---+---+---+---+---+---+ |R 4|U 4|L 3|D 1|R 4|D 1|L 5|R 2| +---+---+---+---+---+---+---+---+
I'll do this in a script. I'll have a verb that moves in a given direction, and make each of the R/U/L/D verbs call it:
'`R U L D' =: (0 1&move)`(_1 0&move)`(0 _1&move)`(1 0&move)
Initialize positions and tail track. The track will be a table so that adding a list makes a new row rather than extending a list.
hpos =: 0 0 [ tpos =: 0 0 [ track =: ,:0 0
The verb to move:
move =: {{ for. i. y do. hpos =: hpos + x NB. move head if. 1 < >./ | hpos - tpos do. tpos =: tpos + * hpos - tpos end. NB. if not touching, move tail toward head track =: track , tpos end. i. 0 0 NB. quiet result }}
I load the script, run the lines, and display the number of cells (after discarding duplicates).
".@> lines # ~. track 13
In part 2 the rope has been extended to 10 knots. I'll use the same framework as before, but now the update needs to ripple through all the knots. That is a job for suffix scan (u/\. y) which applies u between the last 2 items, then between the 3d-last item and the first result, etc. Since this runs back-to-front I will make the head the last item in the rope. The new script is
'`R U L D' =: (0 1&move)`(_1 0&move)`(0 _1&move)`(1 0&move) rope =: 10 2$0 0 [ track =: ,:0 0 move =: {{ for. i. y do. rope =: (x + {: rope) _1} rope NB. move head (the last item) rope =: {{ if. 1 < >./ | y - x do. x =. x + * y - x end. x }}/\. rope NB. if not touching, move x toward y track =: track , {. rope NB. Remember track of last knot end. i. 0 0 NB. quiet result }}
I run it on the larger example dataset.
]lines =: < onaoclines +---+---+---+---+----+----+----+----+ |R 5|U 8|L 8|D 3|R 17|D 10|L 25|U 20| +---+---+---+---+----+----+----+----+ ".@> lines # ~. track 36