Day 11
This commit is contained in:
		
							parent
							
								
									2d6fac90f6
								
							
						
					
					
						commit
						54caefb22e
					
				
							
								
								
									
										55
									
								
								11/input
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								11/input
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
				
			||||||
							
								
								
									
										136
									
								
								11/solution.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								11/solution.mjs
									
									
									
									
									
										Normal file
									
								
							@ -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
	
	Block a user