Rules: no spoilers.
The other rules are made up as we go along.
Share code by link to a forge, home page, pastebin (Eric Wastl has one here) or code section in a comment.
Rules: no spoilers.
The other rules are made up as we go along.
Share code by link to a forge, home page, pastebin (Eric Wastl has one here) or code section in a comment.
I liked the slight trickiness of part 2, that the naive implementation would never complete in time.
As always doing a JQ implementation:
Part 1
#!/usr/bin/env jq -n -R -f # Get seeds input | [ match("\\d+"; "g").string | tonumber ] as $seeds | # Collect maps reduce inputs as $line ({}; if $line == "" then . elif $line | test(":") then .k = ( $line / " " | .[0] ) else .[.k] += [[ $line | match("\\d+"; "g").string | tonumber ]] end ) # For each map, apply transformation to all seeds. # seed -> ... -> location | reduce ( to_entries[] | select(.key != "k") .value) as $map ({s:$seeds}; .s[] |= ( # Only attempt transform if element is in one of the ranges [ . as $e | $map[] | select(. as [$d,$s,$l] | $e >= $s and $e < $s + $l) ] as $range | if ($range | length ) > 0 then $range[0] as [$d,$s] | . - $s + $d else . end ) ) # Get lowest location | .s | min
Some comments:
input
first to get the seeds, theninputs
to get remaining lines.Part 2
#!/usr/bin/env jq -n -R -f # Utility function def group_of($n): ( length / $n ) as $l | . as $arr | range($l) | $arr[.*$n:.*$n+$n] ; # Get all seed ranges input | [ match("\\d+"; "g").string | tonumber ] | [group_of(2)] as $seeds | # Collect maps reduce inputs as $line ({}; if $line == "" then . elif $line | test(":") then .k = ( $line / " " | .[0] ) else .[.k] += [[ $line | match("\\d+"; "g").string | tonumber ]] end ) # For each map, apply transformation to all seeds ranges. # Producing new seed ranges if applicable # seed -> ... -> location | reduce (to_entries[] | select(.key != "k") .value) as $map ({s:$seeds}; .s |= [ # Only attempt transform if seed range and map range instersect .[] | [.[0], add, .[1] ] as [$ea, $eb, $el] | [ $map[] | select(.[1:] | [.[0], add ] as [$sa,$sb] | ( $ea >= $sa and $ea < $sb ) or ( $eb >= $sa and $eb < $sb ) or ( $sa >= $ea and $sa < $eb ) ) ] as $range | if $range | length > 0 then $range[0] as [$d,$s,$l] | # ( only end ) inside map range if $ea < $s and $eb < $s + $l then [$ea, $s - $ea], [$d, $eb - $s ] # ( both start, end ) outside map range elif $ea < $s then [$ea, $s - $ea], [$d, $l], [ $s + $l, $eb ] # ( only start ) inside map range elif $eb > $s + $l then [$ea + $d - $s, $l - $ea + $s ], [$s + $l, $eb - $s - $l] # ( both start, end ) inside map range else [$ea + $d - $s , $el] end else . end ] ) # Get lowest location | [.s[][0]] | min
Some comments:
[1,2,3] | [ .[] | if . == 2 then . * 10 + 1 , . * 10 + 2 else . end ]
->[1, 21, 22, 3]
Replaced less-than (and greater-than for symmetry) symbols with full-width version, since lemmy apparently doesn’t handle them well within a code block: replacing less than with <
Part 2 is a classic AoC move, where suddenly the problem space becomes much larger.
JQ looks like magic. So short! So clean! What’s the catch?
The main catch is it would often be faster to use a “real” programming langage ^^, both in writing the code, and in execution time for some loop heavy examples: equivalent code that completes say in 1 second in python, completing in 1 minute in jq. Also missing a way to call native libraries, to do stuff like say “md5” (relevant) in past years advents-of-code.
That being said i like the general “pipe”, map-reduce feel of the language. Like bash one-liners It can make for very terse implementations. I like to add comments, and indentation to make it readable though.
Thanks for the insight!