AOC Day 5: Hydrothermal Venture

You come across a field of hydrothermal vents on the ocean floor! These vents constantly produce large, opaque clouds, so it would be best to avoid them if possible. [more…]

This post contains solutions!

Each vent is defined by two co-ordinate pairs. We’ll represent the vents as a list of 2×2 matrices.

q)showvents:{value"(",ssr[;"-\>";";"]x,")"}eachread0`:test5.txt0959800894342221707464200929341400885582q)firstvents0959

Part 1

The second coords match so the first vent is a horizontal line through

091929394959

which we could express as (range 0 5),'range 9 9. We need only

q)rng:{x+tily-x-1} / ascending rangeq)range:{@[;x](reverserngreverse@;rng;first)2sv(=;<).\:x} q)rangeeach(59;53;99)567895439

to get the points crossed by a vent.

Note how range tests its argument pair for both equality and ascending, takes the resulting boolean pair as a decimal and indexes a list of three functions – equivalent to a case statement. But we can do better. If we move the test for equality into rng, both functions can be expressed with the ternary conditional Cond.

q)rng:{$[x=y;x;x+tily-x-1]}. / range (not descending)q)range:{$[.[>]x;reverserngreversex;rngx]} q)pts:{.[,']rangeeachflipx} q)([]v:vents;p:ptseachvents) v p ---------------------------------------------0959(09;19;29;39;49;59)8008(80;71;62;53;44;35;26;17;08)9434(94;84;74;64;54;44;34)2221(22;21)7074(70;71;72;73;74)6420(64;53;42;31;20)0929(09;19;29)3414(34;24;14)0088(00;11;22;33;44;55;66;77;88)5582(55;64;73;82)

We notice with satisfaction that pts finds the points for diagonal vents as well as vertical and horizontal ones.

Find the points for just horizontal and vertical vents:

q)ventswhere{any.[=]x}eachvents095994342221707409293414q)ptseachventswhere{any.[=]x}eachvents(09;19;29;39;49;59) (94;84;74;64;54;44;34) (22;21) (70;71;72;73;74) (09;19;29) (34;24;14) q)counteachgrouprazeptseachventswhere{any.[=]x}eachvents09|219|229|239|149|159|194|184|174|264|154|144|134|222|121|170|171|172|173|124|114|1

And count the points where vents overlap.

q)plot:{counteachgrouprazeptseachx} q)chp:{countwhere1<x} / count hot pointsq)chpplotventswhere{any.[=]x}eachvents5

Part 2

The general case simply stops excluding the diagonal vents.

q)chpplotvents12

We can also check our work against the map. For this we’ll represent the 10×10 map as a 100-item vector and map the co-ordinate pairs into the range 0-99.

q)flip" 1234"10cut{@[100#0;keyx;:;valuex]}counteachgroup10sv'razeptseachvents"1 1 11 "" 111 2 "" 2 1 111 "" 1 2 2 "" 112313211"" 1 2 "" 1 1 "" 1 1 ""1 1 ""222111 "

That leaves our complete solution:

vents:{value"(",ssr[;"-\>";";"]x,")"}eachread0`:day5.txtrng:{$[x=y;x;x+tily-x-1]}. / range (ascending only)range:{$[.[>]x;reverserngreversex;rngx]}pts:{.[,']rangeeachflipx} / points of a ventplot:{counteachgrouprazeptseachx}chp:{countwhere1<x} / count hot pointsa[`$"5-1"]:chpplotventswhere{any.[=]x}eachventsa[`$"5-2"]:chpplotvents