From 54caefb22e7a42587200219607010c2cc3b42204 Mon Sep 17 00:00:00 2001 From: Ben Ashton Date: Sun, 11 Dec 2022 22:26:41 -0700 Subject: [PATCH] Day 11 --- 11/input | 55 ++++++++++++++++++++ 11/solution.mjs | 136 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 11/input create mode 100644 11/solution.mjs diff --git a/11/input b/11/input new file mode 100644 index 0000000..e230ab0 --- /dev/null +++ b/11/input @@ -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 diff --git a/11/solution.mjs b/11/solution.mjs new file mode 100644 index 0000000..1c7c39f --- /dev/null +++ b/11/solution.mjs @@ -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}` +);