! round toward zero def(trunc) /\.\d*/ => "" ! evaluate formula def(operate) #( 'old' => { get(old) } /(\d+) \* (\d+)/ => { $1 $2 * } /(\d+) \+ (\d+)/ => { $1 $2 + } ) #( ! capture input fx ( /Monkey \d+/ => { _ set(currmonkey) inc(monkeys) } /Starting items: .+/ => /\d+/ => { _ get(currmonkey) " items" cat push } /Operation: new = (.+)/ => { $1 push(operation) } /Test: divisible by (\d+)/ => { $1 push(divisor) } /If true: throw to monkey (\d+)/ => { $1 push(truetarget) } /If false: throw to monkey (\d+)/ => { $1 push(falsetarget) } ) { ! run simulation 20 times { 0 set(i) drop get(monkeys) times { "Monkey " get(i) " items" cat cat for { get(i) push(target) _ set(old) drop get(i) getat(operation) do(operate) 3 / do(trunc) copy get(i) getat(divisor) % 0 = if { get(i) getat(truetarget) } { get(i) getat(falsetarget) } "Monkey " swap " items" cat cat push } "Monkey " get(i) " items" cat cat empty inc(i) } } ! sort toss targets and print them all flat sort(target) for(target) { _ " " } } ! group toss targets /\b(\d+ )(?!\1)/ => { $1 "\n" } ! count targets within each group /.+/ => #( fx { 0 set(count) } /\d+/ => fx { inc(count) } { get(count) 6 zpad } ) ! find the hottest toss targets /.+/ => fx { _ push(inspections) } { sort(inspections) pop(inspections) pop(inspections) * } )