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.
Have been mostly using jq for fun.
Day 1
Part 1
#!/usr/bin/env jq -n -R -f # Get and reduce every "pretty" line reduce inputs as $line ( 0; # Add extracted number . + ( $line / "" | [ .[] | tonumber? ] | [first * 10 , last] | add ) )
First part was easy, and very suited to jq
Part 2
#!/usr/bin/env jq -n -R -f # Define string to num value map { "one": 1, "1": 1, "two": 2, "2": 2, "three": 3, "3": 3, "four": 4, "4": 4, "five": 5, "5": 5, "six": 6, "6": 6, "seven": 7, "7": 7, "eight": 8, "8": 8, "nine": 9, "9": 9 } as $to_num | # Get and reduce every "pretty" line reduce inputs as $line ( 0; . + ( $line | # Try two capture two numbers capture("(^.*?(?(one|two|three|four|five|six|seven|eight|nine|[1-9])).*(?(one|two|three|four|five|six|seven|eight|nine|[1-9])).*?$)?") | # If no capture, get one number twice if .f == "" then $line | capture("^.*?(?(one|two|three|four|five|six|seven|eight|nine|[1-9]))") | .l = .f else . end | # Add extracted number $to_num[.f] * 10 + $to_num[.l] ) )
Second part was harder than expected, i had to resort to regex.
Day 2
Part 1
#!/usr/bin/env jq -n -R -f # For each game: Is 12 red cubes, 13 green cubes, and 14 blue cubes possible ? # Line Format = # Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green [ # Splitting input game id and content inputs / ": " | # Saving id (.[0] / " " | .[1] | tonumber ) as $id | # Parsing game .[1] / "; " | [ .[] / ", " | [ .[] / " " | {(.[1]): .[0] | tonumber} ] | add | # Is given sample possible ? .red <= 12 and .green <= 13 and .blue <= 14 ] | # If all samples possible, return id, else 0 if all then $id else 0 end ] | # Return sum of all possible game ids add
Not too much trickery in this example.
Part 2
#!/usr/bin/env jq -n -R -f # Line Format = # Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green [ # Splitting input game id and content inputs / ": " | # Parsing game .[1] / "; " | [ .[] / ", " | [ .[] / " " | {(.[1]): .[0] | tonumber} ] | add ] | # Getting minimum required mumber for each color, # and computing the power { r: ([.[].red] | max), g: ([.[].green] | max), b: ([.[].blue] | max) } | .r * .g * .b ] | # Return sum of all powers add
Satisifyingly straightfoward edit form part one.
Day 3
Part 1
#!/usr/bin/env jq -n -R -f # Getting input with padding, and padded width [ "." + inputs + "." ] as $inputs | ( $inputs[0] | length ) as $w | # Working with flattened string, convert all symbols to '#' [ ([range($w) | "."]|join("")), # Padding $inputs[], ([range($w) | "."]|join("")) # Padding ] | join("") | gsub("[^0-9.]";"#") as $inputs | reduce ( # Get all indices for symbols, in box pattern around symbols $inputs | indices("#")[] | . - $w -1 , . - $w , . - $w + 1 , . - 1 , empty , . + 1 , . + $w - 1 , . + $w , . + $w + 1 ) as $i ( # Numbers containes bounding indices, # of numbers bordering symbols {numbers: []}; # Test if current index isn't included in any found number def new_number($i): [ .numbers[] | .[0] <= $i and $i <= .[1] ] | any | not ; # Make "number" as bounding indices, by extending left and right def make_number($i): {a: $i, b: ($i+1 )} | until( $inputs[.a:.b] | test("^[^0-9]"); .a -= 1 ) | until( $inputs[.a:.b] | test("[^0-9]$"); .b += 1 ) | [ .a +1 , .b -1 ] ; # Add numbers if bordering symbol and new if ($inputs[$i:$i+1] | test("[0-9]")) and new_number($i) then .numbers += [ make_number($i) ] else . end ) | # Output sum of all found numbers [ .numbers[] | $inputs[.[0]:.[1]] | tonumber ] | add
Took More time than i expected, glad i had the idea early to search by the indices of the symbols and not the digits. Not super well suited to jq, unless I’m missing a better solution.
Part 2
#!/usr/bin/env jq -n -R -f # Getting input with padding, and padded width [ "." + inputs + "." ] as $inputs | ( $inputs[0] | length ) as $w | # Working with flattened string, only keep gear '*' symbols [ ([range($w) | "."]|join("")), # Padding $inputs[], ([range($w) | "."]|join("")) # Padding ] | join("") | gsub("[^0-9*]";".") as $inputs | # Iterate over index positions of all gears reduce ($inputs | indices("*")[]) as $i ( 0; # Re-use part-1 functions def new_number($i): [ .numbers[] | .[0] <= $i and $i <= .[1] ] | any | not ; def make_number($i): {a: $i, b: ($i+1 )} | until( $inputs[.a:.b] | test("^[^0-9]"); .a -= 1 ) | until( $inputs[.a:.b] | test("[^0-9]$"); .b += 1 ) | [ .a +1 , .b -1 ] ; # Reset and add numbers for each "box" ids def add_numbers($box_idx): reduce $box_idx[] as $i ({numbers:[]}; if ($inputs[$i:$i+1] | test("[0-9]")) and new_number($i) then .numbers += [ make_number($i) ] else . end ) ; add_numbers([ $i - $w -1 , $i - $w , $i -$w + 1 , $i - 1 , empty , $i + 1 , $i + $w - 1, $i + $w , $i + $w + 1 ]).numbers as $numbers | if $numbers | length == 2 then # Add product if exactly two bordering numbers . += ( $numbers | map($inputs[.[0]:.[1]]|tonumber) | .[0] * .[1] ) else . end )
Not too far of an edit from part one.