My (attempted) solutions to the 2022 Advent of Code
Log | Files | Refs | README

```commit 3ae71a1a33ea04c65ce374ba6f50842a30c15ece
parent d80bf49b1568fcee28bddd26f667a5de50943b16
Date:   Sun, 11 Dec 2022 14:57:27 -0800

Solution to day 11, part 1.

7 minutes after the "deadline". :(

Diffstat:
Asrc/day_11.jl | 155+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
```
```1 file changed, 155 insertions(+), 0 deletions(-)
diff --git a/src/day_11.jl b/src/day_11.jl
@@ -0,0 +1,155 @@
+#!/usr/bin/env julia
+
+    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"""))
+
+# Parsing this input is going to be a job, so I'm going to give myself
+# permission to write as many tiny functions as I want to (easier to debug).
+
+    mutable struct Monkey
+        id::Int
+        items::Vector{Int}
+        operation::AbstractString
+        divisible::Int
+        throw_id::Tuple{Int,Int}
+        considerations::Int
+    end
+
+    # This parses the text and creates a Monkey. Not sure if this is the normal
+    # Julia approach, but outer constructors are so flexible it seems
+    # reasonable?
+    function Monkey(monkeytext::Vector{<:AbstractString})
+        monkeyregexes = [
+            r"^Monkey (\d+):\$",
+            r"^  Starting items: ([0-9, ]*)\$",
+            r"^  Operation: new = (.*)\$",
+            r"^  Test: divisible by (\d+)\$",
+            r"^    If true: throw to monkey (\d+)\$",
+            r"^    If false: throw to monkey (\d+)\$"
+        ]
+        monkeymatches = map(match, monkeyregexes, monkeytext)
+        @assert !any(map(isnothing, monkeymatches))
+
+        Monkey(
+            parse(Int, monkeymatches[1].captures[1]),
+            parse.(Int, split(monkeymatches[2].captures[1], ", ")),
+            monkeymatches[3].captures[1],
+            parse(Int, monkeymatches[4].captures[1]),
+            (
+                parse(Int, monkeymatches[5].captures[1]),
+                parse(Int, monkeymatches[6].captures[1])
+            ),
+            0
+        )
+    end
+
+    """
+    Apply the operation to see how the worry level changes.
+
+    This is a hacky/brittle approach! But it works for the little code puzzle.
+    """
+    function monkeyinspection(monkey::Monkey, worry::Int)
+        operation = replace(monkey.operation, "old" => worry)
+        eval(Meta.parse(operation))
+    end
+
+    """
+    Test worry level and return the id of the monkey that will receive the item.
+    """
+    function monkeytest(monkey::Monkey, worry::Int)
+        worry % monkey.divisible == 0 ? monkey.throw_id[1] : monkey.throw_id[2]
+    end
+
+    """
+    Process one monkey's turn.
+    """
+    function monkeyturn!(monkey::Monkey,
+                         monkeys::Dict{Int, Monkey})
+        while !isempty(monkey.items)
+            item = popfirst!(monkey.items)
+            item = monkeyinspection(monkey, item)
+            item รท= 3
+            push!(monkeys[monkeytest(monkey, item)].items, item)
+            monkey.considerations += 1
+        end
+    end
+
+    function monkeyrounds!(monkeys::Dict{Int, Monkey}, numrounds::Int)
+        monkeyids = sort(collect(keys(monkeys)))
+        for _ = 1:numrounds
+            for monkeyid = monkeyids
+                monkeyturn!(monkeys[monkeyid], monkeys)
+            end
+        end
+    end
+
+    """
+    Split the input lines into (unparsed text representations) of each monkey.
+
+    Returns an array of string arrays.
+    """
+    function split_monkeys(input::Vector{<:AbstractString})
+        monkeystart = 1
+        monkeys = Vector{Vector{<:AbstractString}}()
+        for monkeyend = [findall(==(""), input); lastindex(input)+1]
+            push!(monkeys, input[monkeystart:monkeyend-1])
+            monkeystart = monkeyend+1
+        end
+        monkeys
+    end
+
+    """
+    Read the input and return a dictionary of monkeys.
+    """
+    function makemonkeys(input::Vector{<:AbstractString})
+        monkeys = map(Monkey, split_monkeys(input))
+        Dict(zip([m.id for m in monkeys], monkeys))
+    end
+end
+
+function part_1(input)
+    reduce(
+        *,
+        partialsort(map(x->x.considerations, values(monkeys)),
+                    1:2, rev = true)
+    )
+end
+@assert part_1(example) == 10605
+@info part_1(input)
+
+function part_2(input)
+    nothing
+end
+@info part_2(input)
```