Advent Of Code 2021 solutions in Text Munge. https://munge.netlify.app/
Why? I don't know.
Part 1
#(
/(\d+)\s+(?=(\d+))/ => {
$2 $1 >> if { inc(deepercount) }
}
{ get(deepercount) }
)
Part 2
#(
/(\d+)\s+(?=\d+\s+\d+\s+(\d+))/ => {
$2 $1 >> if { inc(deepercount) }
}
{ get(deepercount) }
)
Part 1
#(
fx { 0 set(x) set(y) }
(
/forward (\d+)/ => { get(x) $1 + set(x) }
/up (\d+)/ => { get(y) $1 - set(y) }
/down (\d+)/ => { get(y) $1 + set(y) }
)
{ get(x) get(y) * }
)
Part 2
#(
fx { 0 set(x) set(y) set(aim) }
(
/forward (\d+)/ => {
get(x) $1 + set(x)
get(aim) $1 * get(y) + set(y)
}
/up (\d+)/ => { get(aim) $1 - set(aim) }
/down (\d+)/ => { get(aim) $1 + set(aim) }
)
{ get(x) get(y) * }
)
Part 1
def(bitmode) #(
@ /01|10/ => "" ! adjacent opposites vanish
/0+/ => "0"
/1+/ => "1"
)
#(
/.+/ => { _ push(lines) _ len set(width) }
{
0 set(col) drop
"" get(width) times {
for(lines) {
_ get(col) skip 1 take
cat
}
push(cols)
inc(col)
}
0 for(cols) {
2 *
_ do(bitmode) + ! gamma bit
}
set(gamma)
1 get(width) times { 2 * } 1 -
get(gamma) - ! epsilon
*
}
)
Part 2
def(bitmode) #(
@ /01|10/ => "" ! adjacent opposites vanish
/0+/ => "0"
/1+|^$/ => "1" ! default 1
)
def(findO2) {
! get mode of col'th char
"" for(O2lines) { _ get(col) skip 1 take cat }
do(bitmode) set(criteria) drop
! filter
count(O2lines) times {
pop(O2lines)
copy get(col) skip 1 take get(criteria) =
if { cons(O2lines) } { drop }
}
! recurse
count(O2lines) 1 >> if {
inc(col) do(findO2)
}
}
def(findCO2) {
! get mode of col'th char
"" for(CO2lines) { _ get(col) skip 1 take cat }
do(bitmode) set(criteria) drop
! filter
count(CO2lines) times {
pop(CO2lines)
copy get(col) skip 1 take get(criteria) = not
if { cons(CO2lines) } { drop }
}
! recurse
count(CO2lines) 1 >> if {
inc(col) do(findCO2)
}
}
def(unbin) #(
fx { 0 set(unbin) }
/./ => { get(unbin) 2 * _ + set(unbin) }
{ get(unbin) }
)
#(
/.+/ => { ! populate arrays and set dimension
_ push(O2lines)
_ push(CO2lines)
_ len set(width)
}
{
! compute oxygen generator rating
0 set(col) do(findO2)
pop(O2lines) do(unbin) set(O2rating)
! compute CO2 scrubber rating
0 set(col) do(findCO2)
pop(CO2lines) do(unbin) set(CO2rating)
clear get(O2rating) get(CO2rating) *
}
)
Part 1
#(
/ ?\b(\d)\b/ => { 0 $1 } ! zero-fill to two digits
@(
/.*X.*/s => () ! if board is won
/.*/s => #(
/^(\d+),?/ => { $1 set(callnum) clear }
get(callnum) => "__" ! replace called number with __
! in a win, replace _ with X
! row win
/^(?:__ ){4}__$/m => '_' => "X"
! column win
/(?:__(?:\s\w\w){4}\s){4}__/m
=> /__((?:\s\w\w){4})?/
=> /^__/ => "XX"
)
)
( ! keep only the winning board
/(\n.|.)*?X(\n.|.)*/ => ()
/./s => ""
)
/\d+/ => { get(boardtotal) _ + set(boardtotal) }
{ get(boardtotal) get(callnum) * }
)
Part 2
#(
/ ?\b(\d)\b/ => { 0 $1 } ! zero-fill to two digits
@1#(
/(?:\n.|.)*?X(?:\n.|.)*/ => {
! remove winning board but remember it
_ set(board)
get(callnum) set(clearnum)
clear
}
/.*/s => #(
/^(\d+),?/ => { $1 set(callnum) clear }
get(callnum) => "__" ! replace called number with __
! in a win, replace _ with X
! row win
/^(?:__ ){4}__$/m => '_' => "X"
! column win
/(?:__(?:\s\w\w){4}\s){4}__/m
=> /__((?:\s\w\w){4})?/
=> /^__/ => "XX"
)
)
{ get(board) }
/\d+/ => { get(boardtotal) _ + set(boardtotal) }
{ get(boardtotal) get(clearnum) * }
)
Part 1
def(addcloud) {
"clouds" swap cat copy ! build variable name
get 1 + ! get dynamically
swap set ! and store the result
2 = if { inc(multiclouds) }
inc(pos)
}
#(
(
/(\d+),(\d+) -> \1,(\d+)/ => {
$2 $3 min set(pos) drop
$2 $3 max 1 + get(pos) - times
{ ! iterate over line
$1 "," get(pos) cat cat
do(addcloud)
}
}
/(\d+),(\d+) -> (\d+),\2/ => {
$1 $3 min set(pos) drop
$1 $3 max 1 + get(pos) - times
{ ! iterate over line
get(pos) "," $2 cat cat
do(addcloud)
}
}
)
{ get(multiclouds) }
)
Part 2
def(abs) '-' => ""
def(sign) /[1-9]\d*/ => "1"
#(
! match input line
/(\d+),(\d+) -> (\d+),(\d+)/ => {
! calculate directions
$3 $1 - do(sign) set(dx)
$4 $2 - do(sign) set(dy)
! caclulate target iteration count
$3 $1 set(x) - do(abs)
$4 $2 set(y) - do(abs)
max 1 +
times { ! iterate over line
get(x) "," get(y) cat cat
"clouds" swap cat copy ! build variable name
get 1 + ! get dynamically
swap set ! and store the result
2 = if { inc(multiclouds) }
get(x) get(dx) + set(x) drop
get(y) get(dy) + set(y) drop
}
}
{ get(multiclouds) }
)
Part 1
def(day) (
'0' => "68"
/\d/ => { _ 1 - }
)
#(
',' => ""
{
_ 80 times { do(day) }
len
}
)
Part 2
def(day) /^(\d+),((?:\d+,){6})(\d+),(\d+)$/ => {
$2 ! days 0-5
$3 $1 + "," ! day 6
$4 "," ! day 7
$1 ! day 8
}
#(
/\d/ => { _ push(fish) }
{ ! index by cohort
9 times { 0 push(cohort) }
for(fish) {
_ 1 + times { uncons(cohort) }
1 +
_ 1 + times { cons(cohort) }
}
"," join(cohort)
256 times { do(day) }
}
@/(\d+),(\d+)/ => { $1 $2 + }
)
Part 1
def(abs) '-' => ""
#(
/\d+/ => { _ 5 lpad push(pos) }
{
sort(pos)
! find halfway point
count(pos) 2 / floor set(half)
times { pop(pos) }
! retrieve median
set(median)
! put everything back
get(half) times { push(pos) }
! sum total variance
0 for(pos) { _ get(median) - do(abs) + }
}
)
Part 2
def(abs) '-' => ""
#(
fx { "1e99" set(besttarget) set(bestcost) }
/\d+/ => {
_ push(pos)
_ get(min) min set(min)
_ get(max) max set(max)
}
{
get(max) get(min) set(target) -
times {
0 for(pos) {
_ get(target) - do(abs)
copy 1 + * 2 / +
}
set(cost)
get(bestcost) << if {
get(cost) set(bestcost) drop
get(target) set(besttarget) drop
}
inc(target)
}
}
{ get(bestcost) }
)
Part 1
#(
/.*\| / => ""
(
/\b\w{2,4}\b/ => { inc(sum) }
/\b\w{7}\b/ => { inc(sum) }
)
{ get(sum) }
)
Part 2
#(
/.+/ => #(
! one-by-one replace each lowercase character to the
! *correct* uppercase character from the 7-segment
/([a-g])(?=([^|]*?\1){8})/ => fx { $1 set(F) }
get(F) => "F"
{ "abcdefg " _ }
/^\w*([a-g])\w* (?=[^|]*\b(?:\1\w|\w\1)\b)(?=([^|]*?\1){8})/
=> { $1 set(C) drop }
get(C) => "C"
/([a-g])(?=([^|]*?\1){7})/ => fx { $1 set(A) }
get(A) => "A"
{ "abcdefg " _ }
/^\w*([a-g])\w* (?=[^|]*\b(?=\w*\1)\w{4}\b)(?=([^|]*?\1){7})/
=> { $1 set(D) drop }
get(D) => "D"
/([a-g])(?=([^|]*?\1){6})/ => fx { $1 set(G) }
get(G) => "G"
/([a-g])(?=([^|]*?\1){5})/ => fx { $1 set(B) }
get(B) => "B"
/[a-g]/ => "E"
! with all letters now corrected, remove prefix part
/.+\|/ => ""
! sort words
/\w+/ => #(
fx { empty(chars) }
/./ => fx { _ push(chars) }
{ sort(chars) "" join(chars) }
)
(
/ ABCEFG\b/ => "0"
/ CF\b/ => "1"
/ ACDEG\b/ => "2"
/ ACDFG\b/ => "3"
/ BCDF\b/ => "4"
/ ABDFG\b/ => "5"
/ ABDEFG\b/ => "6"
/ ACF\b/ => "7"
/ ABCDEFG\b/ => "8"
/ ABCDFG\b/ => "9"
)
fx { get(sum) _ + set(sum) }
)
{ get(sum) }
)
Part 1
Takes about 30 seconds. transpose
is slow.
def(transpose) #(
fx { empty(lines) }
/.+/ => { _ push(lines) _ len set(width) }
{
0 set(i) drop
get(width) times {
for(lines) { _ get(i) skip 1 take }
"\n" inc(i)
}
}
/\n+$/ => ""
)
#(
/\s+$/ => "" ! normalize ending
( ! put current height in lower right corner
/.+$/ => { _ " \n " 9 _ len lpad }
/.+/m => { _ " " }
)
@#(
/(?=(\d))(?:\B\1|\1\B)(?=.*\1$)/s => " "
{ _ do(transpose) }
/(?=(\d))(?:\B\1|\1\B)(?=.*\1$)/s => " "
{ _ do(transpose) }
! decrement working digit
/[1-9]$/ => { _ 1 - }
/0$/ => ""
)
/\d/ => { _ 1 + get(risk) + set(risk) }
{ get(risk) }
)
Part 2
This is very slow for the full solution, taking more than 15 minutes on my machine.
def(transpose) #(
fx { empty(lines) }
/.+/ => { _ push(lines) _ len set(width) }
{
0 set(i) drop
get(width) times {
for(lines) {
_ get(i) skip 1 take
}
"\n" inc(i)
}
}
)
#(
/\s+$/ => "" ! normalize ending
@ #(
1(/[0-8]/ => "X") ! find start of next basin
@ #( ! flood fill
/[0-8]*X[0-8]*/ => /./ => "X"
{ _ do(transpose) }
/[0-8]*X[0-8]*/ => /./ => "X"
{ _ do(transpose) }
)
fx { 0 set(size) }
/X/ => { inc(size) " " }
fx { get(size) 5 lpad dump push(sizes) }
)
{
"Solution: " sort(sizes) 1 3 times { pop(sizes) * }
"\nBasin removal:\n" _
}
)
Part 1
#(
@(
'()' => ""
'[]' => ""
'{}' => ""
'<>' => ""
)
/[\(\[{<]/ => ""
/(.)?.*\n?/ => { $1 }
(
')' => "3 "
']' => "57 "
'}' => "1197 "
'>' => "25137 "
)
@/(\d+) (\d+)/ => { $1 $2 + }
)
Part 2
#(
@( ! reduce
'()' => ""
'[]' => ""
'{}' => ""
'<>' => ""
)
! remove the invalid
/.*[\)\]}>].*\n?/ => ""
( ! token scores
'(' => " 1"
'[' => " 2"
'{' => " 3"
'<' => " 4"
)
! line scores
@/(\d+) (\d+)$/m => { $2 5 * $1 + }
! accumulate push all scores
/\d+/ => { _ 20 lpad push(scores) }
{ ! median
sort(scores)
count(scores) 2 / floor times { pop(scores) drop }
pop(scores)
0 + ! trim
}
)
Part 1
! Legend:
! F - to flash
! f - flash on cooldown this turn
def(countF) #(
/[^F]/s => ""
{ _ len }
)
def(step) #(
(
'9' => { "F" inc(flashes) }
/\d/ => { _ 1 + }
)
@(
/(?<=(.{1,12})?)(\d)(?=(.{1,12})?)/s => {
$1 12 lpad 3 take "\n" cat
$1 12 lpad 11 skip $2 $3 12 rpad 1 take "\n" cat cat cat cat
$3 12 rpad 9 skip "\n\n" cat
cat cat
do(countF) _ +
copy 9 >> if { drop "F" inc(flashes) }
}
'F' => "f"
)
'f' => "0"
)
{
_ 100 times {do(step)}
clear
get(flashes)
}
Part 2
def(countF) #(
/[^F]/s => ""
{ _ len }
)
def(step) #(
fx { inc(steps) }
(
'9' => { "F" inc(flashes) }
/\d/ => { _ 1 + }
)
@(
/(?<=(.{1,12})?)(\d)(?=(.{1,12})?)/s => {
$1 12 lpad 3 take "\n" cat
$1 12 lpad 11 skip $2 $3 12 rpad 1 take "\n" cat cat cat cat
$3 12 rpad 9 skip "\n\n" cat
cat cat
do(countF) _ +
copy 9 >> if { drop "F" inc(flashes) }
}
'F' => "f"
)
/^(?:f{10}\n?){10}/ => ""
'f' => "0"
)
#(
@ { _ do(step) }
{ get(steps) 1 - }
)
Part 1
#(
/(.+)-(.+)/ => { $1 $2 push $2 $1 push }
"start"
@#(
(
/^.*?\bend$/m => ()
/^(.*?\b(\w+))$\n?/m => {
$1 set(sofar) drop
$2 for { get(sofar) " " _ "\n" }
}
)
/^.*?\b([a-z]+)\b.*?\b\1\b.*$\n?/m => ""
)
/.+/ => { inc(paths) }
{ get(paths) }
)
Part 2
#(
/(.+)-(.+)/ => { $1 $2 push $2 $1 push }
"start"
@#(
(
/^.*?\bend$/m => ()
/^(.*?\b(\w+))$\n?/m => {
$1 set(sofar) drop
$2 for { get(sofar) " " _ "\n" }
}
)
/^.+?\bstart\b.*$\n?/m => ""
/^.*?\b([a-z]+)\b(?=.*?\b\1\b).*?\b([a-z]+)\b(?=.*?\b\2\b).*$\n?/m => ""
)
/.+/ => { inc(paths) }
{ get(paths) }
)
Part 1
def(foldX) /(\d+),(\d+)/ => {
$1 get(pos) 2 * $1 - min "," $2
}
def(foldY) /(\d+),(\d+)/ => {
$1 "," $2 get(pos) 2 * $2 - min
}
#(
/^(.*?)fold along ([xy])=(\d+)\n?/s => {
$3 set(pos) drop
$2 "x" = if { $1 do(foldX) }
$2 "y" = if { $1 do(foldY) }
}
/^(.+)$(?=.*?\b\1\b)/sm => ""
/^\d+,\d+$/m => fx { inc(dots) }
{ get(dots) }
)
Part 2
def(foldX) /(\d+),(\d+)/ => {
$1 get(pos) 2 * $1 - min "," $2
}
def(foldY) /(\d+),(\d+)/ => {
$1 "," $2 get(pos) 2 * $2 - min
}
#(
@#( ! repeat folds
/^(.*?)fold along ([xy])=(\d+)\n?/s => {
$3 set(pos) drop
$2 "x" = if { $1 do(foldX) }
$2 "y" = if { $1 do(foldY) }
}
! eliminate dupes
/^(.+)$(?=.*?\b\1\b)\n?/sm => ""
)
! get bounding box
/(\d+),(\d+)/ => fx {
$1 1 + get(width) max set(width) drop
$2 1 + get(height) max set(height) drop
}
/^/ => "\n" ! now each line is delimited on both ends
{
0 set(row) drop
get(height) times {
0 set(col) drop
get(width) times {
_
"\n" get(col) "," get(row) "\n" cat cat cat cat
index -1 >> if { "#" } { " " }
inc(col)
}
"\n"
inc(row)
}
}
)
Part 1
def(PairInsertion) /(?<=(\w))(?=(\w))/ => { $1 $2 cat get }
#(
/(\w\w) -> (\w)\n?/ => { $2 $1 set $2 push(symbol) clear }
{ _ 10 times { do(PairInsertion) } }
/\w/ => { _ inc }
{
for(symbol) {
_ get 9 lpad " " _ cat cat push(count)
}
sort(count)
uncons(count) " " pop(count) ! least and most common
}
/\s*(\d+).*?(\d+).*/ => { $2 $1 - }
)
Part 2
def(PairInsertion) #(
/([A-Z])([A-Z]) (\d+)/ => {
$1 $1 $2 cat get " " $3 "\n"
$1 $2 cat get $2 " " $3
}
@ /(\w\w) (\d+)\n(.*)\1 (\d+)\n?/s
=> { $1 " " $2 $4 + "\n" $3 }
)
#(
(
/^|$/ => "_"
/(\w\w) -> (\w)\n?/ => { $2 $1 set $2 push(symbol) clear }
/\s/ => ""
)
(
/(\w)(?=(\w))/ => { $1 $2 " 1\n" }
/.$/ => ""
)
{
_ 40 times { do(PairInsertion) }
}
/([A-Z])(?=.*?(\d+))/ => fx {
$1 get $2 + $1 set
$1 push(symbols)
}
{
for(symbol) {
_ get 2 / 15 lpad " " _ cat cat push(count)
}
sort(count)
uncons(count) " " pop(count) ! least and most common
}
/\s*(\d+).*?(\d+).*/ => { $2 $1 - }
)
Part 1
! vars:
! reg maxcost
! reg seen:{x},{y} -> cost
! reg cave:{y} -> input row
! arr queue:{cost} -> {x},{y}
def(GetRisk) /(\d+),(\d+)/ => {
"cave:" $2 cat get
$1 skip 1 take
}
def(QueueVisit) /^(\d+) (\d+,\d+)$/ => {
get(maxcost) $1 max set(maxcost) clear
$2
"queue:" $1 cat push
}
def(Search) /^(\d+) (\d+),(\d+)$/m => {
"seen:" $2 "," $3 cat cat cat get "" = if
{
! mark territory
$1 "seen:" $2 "," $3 cat cat cat set
clear
! format `{cost} {x},{y}`
! left
$2 0 >> if {
$2 1 - "," $3 cat cat copy
do(GetRisk) $1 + swap " " swap cat cat
do(QueueVisit)
}
! up
$3 0 >> if {
$2 "," $3 1 - cat cat copy
do(GetRisk) $1 + swap " " swap cat cat
do(QueueVisit)
}
! right
$2 get(width) 1 - << if {
$2 1 + "," $3 cat cat copy
do(GetRisk) $1 + swap " " swap cat cat
do(QueueVisit)
}
! down
$3 get(height) 1 - << if {
$2 "," $3 1 + cat cat copy
do(GetRisk) $1 + swap " " swap cat cat
do(QueueVisit)
}
}
}
#(
fx { 0 set(height) }
/.+/ => {
_ "cave:" get(height) cat set
inc(height)
_ len set(width)
}
{
"0,0" "queue:0" push
"SearchCost:0"
}
@/^SearchCost:(\d+)$/ => {
$1 set(currcost) drop
get(currcost) get(maxcost) >> not if {
"queue:" get(currcost) cat for {
get(currcost) " " _ cat cat
do(Search)
}
clear "SearchCost:" $1 1 +
}
}
{ "seen:" get(width) 1 - "," get(height) 1 - cat cat cat get }
)
Part 2
! vars:
! reg maxcost
! reg {x},{y} -> cost
! reg cave:{y} -> input row
! arr queue:{cost} -> {x},{y}
def(GetRisk) /(\d+),(\d+)/ => {
"cave:" $2 cat get
$1 skip 1 take
}
def(QueueVisit) /^(\d+) (\d+,\d+)$/ => {
get(maxcost) $1 max set(maxcost) clear
$2
"queue:" $1 cat push
}
def(Search) /^(\d+) (\d+),(\d+)$/m => {
$2 "," $3 cat cat get "" = if
{
! mark territory
$1 $2 "," $3 cat cat set
clear
! format `{cost} {x},{y}`
! left
$2 0 >> if {
$2 1 - "," $3 cat cat copy
do(GetRisk) $1 + swap " " swap cat cat
do(QueueVisit)
}
! up
$3 0 >> if {
$2 "," $3 1 - cat cat copy
do(GetRisk) $1 + swap " " swap cat cat
do(QueueVisit)
}
! right
$2 get(width) 1 - << if {
$2 1 + "," $3 cat cat copy
do(GetRisk) $1 + swap " " swap cat cat
do(QueueVisit)
}
! down
$3 get(height) 1 - << if {
$2 "," $3 1 + cat cat copy
do(GetRisk) $1 + swap " " swap cat cat
do(QueueVisit)
}
}
}
def(Tile) ( '9' => "1" /\d/ => { _ 1 + } )
#(
/(.+)\n*/ => { $1 4 times { copy do(Tile) } "\n" }
/.*/s => { _ 4 times { copy do(Tile) } "\n" }
fx { 0 set(height) }
/.+/ => {
_ "cave:" get(height) cat set
inc(height)
_ len set(width)
}
{
"0,0" "queue:0" push
"SearchCost:0"
}
@/^SearchCost:(\d+)$/ => {
$1 set(currcost) drop
! dump
get(currcost) get(maxcost) >> not if {
"queue:" get(currcost) cat for {
get(currcost) " " _ cat cat
do(Search)
}
"queue:" get(currcost) cat empty
clear
"SearchCost:" $1 1 +
}
}
{ get(width) 1 - "," get(height) 1 - cat cat get }
)
Part 1
def(unbin) #(
fx { 0 set(n) }
/./ => { get(n) 2 * _ + set(n) }
{ get(n) }
)
def(DecodeLiteral) #(
/.(.{4})/ => { $1 }
do(unbin)
)
#(
(
'0' => "0000"
'1' => "0001"
'2' => "0010"
'3' => "0011"
'4' => "0100"
'5' => "0101"
'6' => "0110"
'7' => "0111"
'8' => "1000"
'9' => "1001"
/a/i=> "1010"
/b/i=> "1011"
/c/i=> "1100"
/d/i=> "1101"
/e/i=> "1110"
/f/i=> "1111"
)
(
/(...)100((?:1....)*0....)/ => {
"Literal ver:" $1 do(unbin)
" val:" $2 do(DecodeLiteral)
"\n"
}
/(...)(...)0(.{15})/ => {
"Operator ver:" $1 do(unbin)
" type:" $2 do(unbin)
" sub-packet bits:" $3 do(unbin)
"\n"
}
/(...)(...)1(.{11})/ => {
"Operator ver:" $1 do(unbin)
" type:" $2 do(unbin)
" sub-packets:" $3 do(unbin)
"\n"
}
/0{1,7}$/m => ""
)
/ver:(\d+)/ => { get(vertotal) $1 + set(vertotal) clear }
{ get(vertotal) }
)
Part 2
def(unbin) #(
fx { 0 set(n) }
/./ => { get(n) 2 * _ + set(n) }
{ get(n) }
)
def(DecodeLiteral) #(
/.(.{4})/ => { $1 }
do(unbin)
)
def(Op) {
set(op) drop
get(op) 0 = if { + }
get(op) 1 = if { * }
get(op) 2 = if { min }
get(op) 3 = if { max }
get(op) 5 = if { >> }
get(op) 6 = if { << }
get(op) 7 = if { = }
}
#(
(
'0' => "0000"
'1' => "0001"
'2' => "0010"
'3' => "0011"
'4' => "0100"
'5' => "0101"
'6' => "0110"
'7' => "0111"
'8' => "1000"
'9' => "1001"
/a/i=> "1010"
/b/i=> "1011"
/c/i=> "1100"
/d/i=> "1101"
/e/i=> "1110"
/f/i=> "1111"
)
(
/(...)100((?:1....)*0....)/ => {
"#" $2 do(DecodeLiteral)
" len:" _ len
"\n"
}
/(...)(...)0(.{15})/ => {
"op:" $2 do(unbin)
" sub-packet-bits:" $3 do(unbin)
" len:" _ len
"\n"
}
/(...)(...)1(.{11})/ => {
"op:" $2 do(unbin)
" sub-packets:" $3 do(unbin)
" len:" _ len
"\n"
}
/0{1,7}$/m => ""
)
@(
! sub-packet-bit match min/max/add/prod (todo?)
/^op:\d sub-packet-bits:(\d+) len:(\d+)\n#(\d+) len:\1\b/m => {
"#" $3 " len:" $2 $1 +
}
! single sub-packet min/max/add/prod
/^op:\d sub-packets:1 len:(\d+)\n#(\d+) len:(\d+)/m => {
"#" $2 " len:" $1 $3 +
}
! sum with sub-packets
/^op:(\d) sub-packets:(\d+) len:(\d+)\n#(\d+) len:(\d+)\n#(\d+) len:(\d+)/m => {
"op:" $1 " sub-packets:" $2 1 - " len:" $3 "\n"
"#" $4 $6 $1 do(Op) " len:" $5 $7 +
}
! sum with sub-packet-bits (todo?)
/^op:(\d) sub-packet-bits:(\d+) len:(\d+)\n#(\d+) len:(\d+)\n#(\d+) len:(\d+)/m => {
"op:" $1 " sub-packet-bits:" $2 " len:" $3 "\n"
"#" $4 $6 $1 do(Op) " len:" $5 $7 +
}
! terminal literal
/^#(\d+).*\n*$/ => { $1 }
)
)
Part 1
/x=(\d+)\.\.(\d+), y=(-\d+)\.\.(-\d+)/ => {
$3 -1 * 1 -
copy 1 + * 2 /
}
Part 2
! takes "{x},{y} {dx},{dy}"
! returns 0/1 testing for target hit
def(RunSim) #(
@/(\d+),(-?\d+) (\d+),(-?\d+)/ => {
$1 get(txmax) >>
$2 get(tymin) <<
+ if { 0 } ! passed the target
{
$1 get(txmin) 1 - >>
$2 get(tymax) 1 + <<
* if { 1 } ! direct hit
{
$1 $3 + "," $2 $4 +
" "
$3 $3 0 >> - "," $4 1 -
}
}
}
)
#(
/x=(\d+)\.\.(\d+), y=(-\d+)\.\.(-\d+)/ => fx {
$1 set(txmin) $2 set(txmax) $3 set(tymin) $4 set(tymax)
}
{
0 set(dx) drop
get(txmax) times {
inc(dx)
get(tymin) set(dy) drop
get(tymin) -2 * 1 + times {
"0,0 " get(dx) "," get(dy) cat cat cat
do(RunSim) if { 1 + }
inc(dy)
}
}
}
)
Part 1
def(MarkDepth)
( ! big idea `[]` is for outer use, `{}` is deeply nested
/^/ => fx { 0 set(depth) }
/\[|{/ => { inc(depth) get(depth) 4 >> if { "{" } { "[" } }
/\]|}/ => { dec(depth) get(depth) 3 >> if { "}" } { "]" } }
)
def(Reduce)
@#(
/.+/ => do(MarkDepth)
1(
! explode
/(\d+)?(\D*){(\d+),(\d+)}(\D*)(\d+)?/ => {
$1 len if { $1 $3 + }
$2 0 $5
$6 len if { $6 $4 + }
}
! split
/\d\d+/ => {
"[" _ 2 / floor "," _ 1 + 2 / floor "]"
}
)
)
#(
@1(
/(.+)\n(.+)/ => {
"[" $1 "," $2 "]"
4 times { cat }
do(Reduce)
}
)
! magnitude
@/\[(\d+),(\d+)\]/ => { 3 $1 * 2 $2 * + }
)
Part 2
def(MarkDepth)
( ! big idea `[]` is for outer use, `{}` is deeply nested
/^/ => fx { 0 set(depth) }
/\[|{/ => { inc(depth) get(depth) 4 >> if { "{" } { "[" } }
/\]|}/ => { dec(depth) get(depth) 3 >> if { "}" } { "]" } }
)
def(Reduce)
@#(
/.+/ => do(MarkDepth)
1(
! explode
/(\d+)?(\D*){(\d+),(\d+)}(\D*)(\d+)?/ => {
$1 len if { $1 $3 + }
$2 0 $5
$6 len if { $6 $4 + }
}
! split
/\d\d+/ => {
"[" _ 2 / floor "," _ 1 + 2 / floor "]"
}
)
)
def(Magnitude) @/\[(\d+),(\d+)\]/ => { 3 $1 * 2 $2 * + }
#(
/.+/ => { _ push(input) }
{
for(input) {
_ set(a) drop
for(input) {
_ set(b) drop
get(a) get(b) = not if {
"[" get(a) "," get(b) "]"
4 times { cat }
do(Reduce)
do(Magnitude)
get(maxsum) max set(maxsum)
}
}
}
clear get(maxsum)
}
)