diff --git a/day11/day11.jl b/day11/day11.jl new file mode 100644 index 0000000..7d512e2 --- /dev/null +++ b/day11/day11.jl @@ -0,0 +1,99 @@ +#!/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() diff --git a/day11/example.txt b/day11/example.txt new file mode 100644 index 0000000..30e09e5 --- /dev/null +++ b/day11/example.txt @@ -0,0 +1,27 @@ +Monkey 0: + Starting items: 79, 98 + Operation: new = old * 19 + Test: divisible by 23 + If true: throw to monkey 2 + If false: throw to monkey 3 + +Monkey 1: + Starting items: 54, 65, 75, 74 + Operation: new = old + 6 + Test: divisible by 19 + If true: throw to monkey 2 + If false: throw to monkey 0 + +Monkey 2: + Starting items: 79, 60, 97 + Operation: new = old * old + Test: divisible by 13 + If true: throw to monkey 1 + If false: throw to monkey 3 + +Monkey 3: + Starting items: 74 + Operation: new = old + 3 + Test: divisible by 17 + If true: throw to monkey 0 + If false: throw to monkey 1 diff --git a/day11/input.txt b/day11/input.txt new file mode 100644 index 0000000..d5ddb7d --- /dev/null +++ b/day11/input.txt @@ -0,0 +1,55 @@ +Monkey 0: + Starting items: 83, 88, 96, 79, 86, 88, 70 + Operation: new = old * 5 + Test: divisible by 11 + If true: throw to monkey 2 + If false: throw to monkey 3 + +Monkey 1: + Starting items: 59, 63, 98, 85, 68, 72 + Operation: new = old * 11 + Test: divisible by 5 + If true: throw to monkey 4 + If false: throw to monkey 0 + +Monkey 2: + Starting items: 90, 79, 97, 52, 90, 94, 71, 70 + Operation: new = old + 2 + Test: divisible by 19 + If true: throw to monkey 5 + If false: throw to monkey 6 + +Monkey 3: + Starting items: 97, 55, 62 + Operation: new = old + 5 + Test: divisible by 13 + If true: throw to monkey 2 + If false: throw to monkey 6 + +Monkey 4: + Starting items: 74, 54, 94, 76 + Operation: new = old * old + Test: divisible by 7 + If true: throw to monkey 0 + If false: throw to monkey 3 + +Monkey 5: + Starting items: 58 + Operation: new = old + 4 + Test: divisible by 17 + If true: throw to monkey 7 + If false: throw to monkey 1 + +Monkey 6: + Starting items: 66, 63 + Operation: new = old + 6 + Test: divisible by 2 + If true: throw to monkey 7 + If false: throw to monkey 5 + +Monkey 7: + Starting items: 56, 56, 90, 96, 68 + Operation: new = old + 7 + Test: divisible by 3 + If true: throw to monkey 4 + If false: throw to monkey 1