Ben Ashton
1 year ago
2 changed files with 191 additions and 0 deletions
@ -0,0 +1,55 @@ |
|||||||
|
Monkey 0: |
||||||
|
Starting items: 54, 98, 50, 94, 69, 62, 53, 85 |
||||||
|
Operation: new = old * 13 |
||||||
|
Test: divisible by 3 |
||||||
|
If true: throw to monkey 2 |
||||||
|
If false: throw to monkey 1 |
||||||
|
|
||||||
|
Monkey 1: |
||||||
|
Starting items: 71, 55, 82 |
||||||
|
Operation: new = old + 2 |
||||||
|
Test: divisible by 13 |
||||||
|
If true: throw to monkey 7 |
||||||
|
If false: throw to monkey 2 |
||||||
|
|
||||||
|
Monkey 2: |
||||||
|
Starting items: 77, 73, 86, 72, 87 |
||||||
|
Operation: new = old + 8 |
||||||
|
Test: divisible by 19 |
||||||
|
If true: throw to monkey 4 |
||||||
|
If false: throw to monkey 7 |
||||||
|
|
||||||
|
Monkey 3: |
||||||
|
Starting items: 97, 91 |
||||||
|
Operation: new = old + 1 |
||||||
|
Test: divisible by 17 |
||||||
|
If true: throw to monkey 6 |
||||||
|
If false: throw to monkey 5 |
||||||
|
|
||||||
|
Monkey 4: |
||||||
|
Starting items: 78, 97, 51, 85, 66, 63, 62 |
||||||
|
Operation: new = old * 17 |
||||||
|
Test: divisible by 5 |
||||||
|
If true: throw to monkey 6 |
||||||
|
If false: throw to monkey 3 |
||||||
|
|
||||||
|
Monkey 5: |
||||||
|
Starting items: 88 |
||||||
|
Operation: new = old + 3 |
||||||
|
Test: divisible by 7 |
||||||
|
If true: throw to monkey 1 |
||||||
|
If false: throw to monkey 0 |
||||||
|
|
||||||
|
Monkey 6: |
||||||
|
Starting items: 87, 57, 63, 86, 87, 53 |
||||||
|
Operation: new = old * old |
||||||
|
Test: divisible by 11 |
||||||
|
If true: throw to monkey 5 |
||||||
|
If false: throw to monkey 0 |
||||||
|
|
||||||
|
Monkey 7: |
||||||
|
Starting items: 73, 59, 82, 65 |
||||||
|
Operation: new = old + 6 |
||||||
|
Test: divisible by 2 |
||||||
|
If true: throw to monkey 4 |
||||||
|
If false: throw to monkey 3 |
@ -0,0 +1,136 @@ |
|||||||
|
import { readFileSync } from 'node:fs'; |
||||||
|
|
||||||
|
const input = readFileSync('input', 'utf-8'); |
||||||
|
|
||||||
|
class Item { |
||||||
|
constructor(initialWorryLevel) { |
||||||
|
this.worryLevel = initialWorryLevel; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class Monkey { |
||||||
|
constructor(monkeys, number, items, operation, test, afterInspectHook) { |
||||||
|
this.monkeys = monkeys; |
||||||
|
this.number = number; |
||||||
|
this.items = items; |
||||||
|
this.operation = operation; |
||||||
|
this.test = test; |
||||||
|
this.afterInspectHook = afterInspectHook; |
||||||
|
|
||||||
|
this.inspectCount = 0; |
||||||
|
} |
||||||
|
|
||||||
|
processItem() { |
||||||
|
const item = this.items.shift(); |
||||||
|
item.worryLevel = this.operation(item.worryLevel); |
||||||
|
this.inspectCount++; |
||||||
|
this.afterInspectHook?.(item); |
||||||
|
const passToMonkey = this.monkeys.get(this.test.test(item.worryLevel)); |
||||||
|
passToMonkey.items.push(item); |
||||||
|
} |
||||||
|
|
||||||
|
processItems() { |
||||||
|
while (this.items.length) { |
||||||
|
this.processItem(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class Test { |
||||||
|
constructor(divisibleBy, trueCondition, falseCondition) { |
||||||
|
this.divisibleBy = divisibleBy; |
||||||
|
this.trueCondition = trueCondition; |
||||||
|
this.falseCondition = falseCondition; |
||||||
|
} |
||||||
|
|
||||||
|
test(worryLevel) { |
||||||
|
return worryLevel % this.divisibleBy === 0 ? |
||||||
|
this.trueCondition : |
||||||
|
this.falseCondition; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export function getMonkeys(afterInspectHook) { |
||||||
|
const monkeys = new Map(); |
||||||
|
input |
||||||
|
.split('\n\n') |
||||||
|
.filter(monkeyData => /\S/.test(monkeyData)) |
||||||
|
.forEach(monkeyData => { |
||||||
|
let number; |
||||||
|
let items; |
||||||
|
let operation; |
||||||
|
let test; |
||||||
|
monkeyData |
||||||
|
.trim() |
||||||
|
.split(/\n (?=\S)/) |
||||||
|
.forEach(data => { |
||||||
|
if (data.startsWith('Monkey')) { |
||||||
|
number = parseInt(data.match(/\d+/)[0]); |
||||||
|
} else if (data.startsWith('Starting items')) { |
||||||
|
items = data |
||||||
|
.split(': ', 2)[1] |
||||||
|
.split(', ') |
||||||
|
.map(worryLevel => new Item(parseInt(worryLevel))); |
||||||
|
} else if (data.startsWith('Operation')) { |
||||||
|
operation = new Function( |
||||||
|
'old', |
||||||
|
`return ${data.split('new = ', 2)[1].trim()}` |
||||||
|
); |
||||||
|
} else if (data.startsWith('Test')) { |
||||||
|
const divisibleBy = parseInt(data.match(/divisible by (\d+)/)[1]); |
||||||
|
const trueCondition = parseInt(data.match(/true[^\n]*(\d+)/)[1]); |
||||||
|
const falseCondition = parseInt(data.match(/false[^\n]*(\d+)/)[1]); |
||||||
|
test = new Test(divisibleBy, trueCondition, falseCondition); |
||||||
|
} |
||||||
|
}); |
||||||
|
monkeys.set( |
||||||
|
number, |
||||||
|
new Monkey(monkeys, number, items, operation, test, afterInspectHook) |
||||||
|
); |
||||||
|
}); |
||||||
|
|
||||||
|
return monkeys; |
||||||
|
} |
||||||
|
|
||||||
|
export function simulateRounds(monkeys, nRounds) { |
||||||
|
for (let round = 0; round < nRounds; round++) { |
||||||
|
for (const number of [...monkeys.keys()].sort()) { |
||||||
|
const monkey = monkeys.get(number); |
||||||
|
|
||||||
|
monkey.processItems(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function calculateMonkeyBusinessLevel(monkeys) { |
||||||
|
return [...monkeys.values()] |
||||||
|
.sort((m1, m2) => m2.inspectCount - m1.inspectCount) |
||||||
|
.slice(0, 2) |
||||||
|
.map(monkey => monkey.inspectCount) |
||||||
|
.reduce((total, monkeyBusiness) => total * monkeyBusiness); |
||||||
|
} |
||||||
|
|
||||||
|
let monkeys; |
||||||
|
let monkeyBusinessLevel; |
||||||
|
|
||||||
|
monkeys = getMonkeys( |
||||||
|
item => item.worryLevel = Math.floor(item.worryLevel / 3) |
||||||
|
); |
||||||
|
simulateRounds(monkeys, 20); |
||||||
|
monkeyBusinessLevel = calculateMonkeyBusinessLevel(monkeys); |
||||||
|
console.log( |
||||||
|
`Level of monkey business after 20 rounds: ${monkeyBusinessLevel}` |
||||||
|
); |
||||||
|
|
||||||
|
monkeys = getMonkeys(item => { |
||||||
|
const commonMultiple = [...monkeys.values()] |
||||||
|
.map(monkey => monkey.test.divisibleBy) |
||||||
|
.reduce((total, divisibleBy) => total * divisibleBy); |
||||||
|
// Reduce item by commonMultiple whenever it exceeds that value
|
||||||
|
return item.worryLevel = item.worryLevel % commonMultiple; |
||||||
|
}); |
||||||
|
simulateRounds(monkeys, 10000); |
||||||
|
monkeyBusinessLevel = calculateMonkeyBusinessLevel(monkeys); |
||||||
|
console.log( |
||||||
|
`Level of monkey business after 10000 rounds: ${monkeyBusinessLevel}` |
||||||
|
); |
Loading…
Reference in new issue