Skip to content

Commit

Permalink
day 11
Browse files Browse the repository at this point in the history
  • Loading branch information
kgeri committed Dec 11, 2022
1 parent c3acfa4 commit 988450b
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 0 deletions.
102 changes: 102 additions & 0 deletions src/main/kotlin/me/gergo/Aoc11.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package me.gergo

import java.io.File
import java.util.*

private const val Rounds = 10000

/**
* Note: this only has Part Two, as I did Part One with a naiive solution that probably takes all the memory in the world, multiplying horribly large
* BigDecimals :) The trick in this one is to remember but delay the computation for as long as possible. As we're only really interested in whether
* the result at the end of a long chain of operations is divisible by N, we can modulo N per every operation - but we must do that for each monkey
* individually, which means we must remember the computation chain (Items.operations in this implementation)!
*/
fun main() {
val monkeys = File("src/main/resources/input11.txt").readText().split("\n\n")
.map { it.split("\n") }
.map(::parseMonkey)


for (i in 1..Rounds) {
for (monkey in monkeys) {
monkey.inspectAndThrowAll(monkeys)
}
}

for (monkey in monkeys) {
println("Monkey ${monkey.name} inspected items ${monkey.inspections} times")
}

val result = monkeys.map(Monkey::inspections).sortedDescending().take(2).reduce(Long::times)
println("Level of monkey business: $result")
}

private class Monkey(val name: Int, val items: Queue<Item>, val operation: Operation, val divisor: Int, val throwToTrue: Int, val throwToFalse: Int) {
var inspections = 0L

fun inspectAndThrowAll(monkeys: List<Monkey>) {
while (true) {
val item = items.poll() ?: return
item.operations.add(operation)
inspections++
val throwTo = if (item.divisibleBy(divisor)) throwToTrue else throwToFalse
monkeys[throwTo].catch(item)
}
}

fun catch(item: Item) {
items.add(item)
}
}

private data class Item(val value: Int, val operations: MutableList<Operation>) {
fun divisibleBy(divisor: Int): Boolean {
var current = value
for (operation in operations) {
current = when (operation) {
is Mul -> (current * operation.multiplier) % divisor
is Add -> (current + operation.add) % divisor
Square -> (current * current) % divisor
}
}
return current % divisor == 0
}
}

private sealed interface Operation
private data class Mul(val multiplier: Int) : Operation
private data class Add(val add: Int) : Operation
private object Square : Operation

private fun parseMonkey(lines: List<String>): Monkey {
val name = lines[0].replace(Regex("\\D+"), "").toInt()
val items = lines[1].substring(" Starting items: ".length).split(", ").map { Item(it.toInt(), mutableListOf()) }
val operation = parseOperation(lines[2].substring(" Operation: new = ".length))
val divisor = lines[3].substring(" Test: divisible by ".length).toInt()
val throwToTrue = lines[4].substring(" If true: throw to monkey ".length).toInt()
val throwToFalse = lines[5].substring(" If false: throw to monkey ".length).toInt()
return Monkey(
name,
items.toCollection(LinkedList()),
operation,
divisor,
throwToTrue,
throwToFalse
)
}

private fun parseOperation(value: String): Operation {
val mr = Regex("(\\w+) ([*+]) (\\w+)").matchEntire(value)!!
assert(mr.groupValues[1] == "old")
val op = mr.groupValues[2]
val opB = mr.groupValues[3]
return if (op == "*") {
if (opB == "old") {
Square
} else {
Mul(opB.toInt())
}
} else {
Add(opB.toInt())
}
}
55 changes: 55 additions & 0 deletions src/main/resources/input11.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Monkey 0:
Starting items: 89, 84, 88, 78, 70
Operation: new = old * 5
Test: divisible by 7
If true: throw to monkey 6
If false: throw to monkey 7

Monkey 1:
Starting items: 76, 62, 61, 54, 69, 60, 85
Operation: new = old + 1
Test: divisible by 17
If true: throw to monkey 0
If false: throw to monkey 6

Monkey 2:
Starting items: 83, 89, 53
Operation: new = old + 8
Test: divisible by 11
If true: throw to monkey 5
If false: throw to monkey 3

Monkey 3:
Starting items: 95, 94, 85, 57
Operation: new = old + 4
Test: divisible by 13
If true: throw to monkey 0
If false: throw to monkey 1

Monkey 4:
Starting items: 82, 98
Operation: new = old + 7
Test: divisible by 19
If true: throw to monkey 5
If false: throw to monkey 2

Monkey 5:
Starting items: 69
Operation: new = old + 2
Test: divisible by 2
If true: throw to monkey 1
If false: throw to monkey 3

Monkey 6:
Starting items: 82, 70, 58, 87, 59, 99, 92, 65
Operation: new = old * 11
Test: divisible by 5
If true: throw to monkey 7
If false: throw to monkey 4

Monkey 7:
Starting items: 91, 53, 96, 98, 68, 82
Operation: new = old * old
Test: divisible by 3
If true: throw to monkey 4
If false: throw to monkey 2

0 comments on commit 988450b

Please sign in to comment.