#!/usr/bin/env julia using Test mutable struct Monkey index :: UInt items :: Vector{Int} op :: Function op_value :: Int test_divisor :: Int test_result :: NTuple{2, UInt} inspected :: Int end function parse_monkey(text) lines = split(text, '\n') # Monkey 0: match_index = match(r"Monkey (\d+):", lines[1]) index = parse(UInt, match_index.captures[1]) # Starting items: 79, 98 match_items = match(r" *Starting items: (.*)", lines[2]) items_list = split(match_items.captures[1], ", ") items = parse.(Int, items_list) # Operation: new = old * 19 match_op = match(r" *Operation: new = old (.) (old|\d+)", lines[3]) if match_op.captures[1] == "+" op = + elseif match_op.captures[1] == "*" op = * else throw(DomainError("Unknown op: " * match_op.captures[1])) end if match_op.captures[2] == "old" op = ^ op_value = 2 else op_value = parse(Int, match_op.captures[2]) end # Test: divisible by 13 match_test = match(r" *Test: divisible by (\d+)", lines[4]) test_divisor = parse(Int, match_test.captures[1]) # If true: throw to monkey 1 # If false: throw to monkey 3 match_true = match(r" *If true: throw to monkey (\d+)", lines[5]) match_false = match(r" *If false: throw to monkey (\d+)", lines[6]) test_result = (parse(UInt, match_true.captures[1]) + 1, parse(UInt, match_false.captures[1]) + 1) return Monkey(index, items, op, op_value, test_divisor, test_result, 0) end function read_monkeys(infile) open(infile) do io monkey_strings = split(read(io, String), "\n\n") return parse_monkey.(monkey_strings) end end function simian_shenanigans(monkeys :: Vector{Monkey}) for m in monkeys for item in m.items new_value = m.op(item, m.op_value) new_value = Int(floor(new_value / 3)) new_monkey = (mod(new_value, m.test_divisor) == 0 ? m.test_result[1] : m.test_result[2]) push!(monkeys[new_monkey].items, new_value) m.inspected += 1 end empty!(m.items) end end function monkey_business(monkeys; rounds=20) for _ in 1:rounds simian_shenanigans(monkeys) end return prod(sort([m.inspected for m in monkeys])[end-1:end]) end function test() @testset "monkey business" verbose=true begin @test monkey_business(read_monkeys("example.txt")) == 10605 @test monkey_business(read_monkeys("input.txt")) == 64032 end end function main() if size(ARGS, 1) == 0 test() else infile = ARGS[1] println("infile = ", infile) monkeys = read_monkeys(infile) display(monkeys) println() println("monkey business ", monkey_business(monkeys)) end end main()