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. Well 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 well 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