Advent of Code 2022 - Day 11: Monkey in the Middle Solution

Math and modulo operation

Part 1

Purely adhoc

Implementation

1const fs = require("fs")
2
3const readData = () => {
4 const data = fs
5 .readFileSync("./input", "utf-8")
6 .split(/\r?\n/)
7 .filter(Boolean)
8
9 const monkeys = {}
10
11 for (let i = 0; i < data.length; i += 6) {
12 const monkeyNumber = i / 6
13 monkeys[monkeyNumber] = {}
14 monkeys[monkeyNumber].items = data[i + 1]
15 .replace("Starting items: ", "")
16 .trim()
17 .replace(/,/g, "")
18 .split(" ")
19 .map(Number)
20
21 monkeys[monkeyNumber].op = (() => {
22 const [operator, operand2] = data[i + 2]
23 .replace("Operation: new = old ", "")
24 .trim()
25 .split(" ")
26
27 const isMirror = operand2 === "old"
28
29 return {
30 "+": (operand, isMirror) => x => x + (isMirror ? x : operand),
31 "-": (operand, isMirror) => x => x - (isMirror ? x : operand),
32 "*": (operand, isMirror) => x => x * (isMirror ? x : operand),
33 "/": (operand, isMirror) => x => x / (isMirror ? x : operand),
34 }[operator](+operand2, isMirror)
35 })()
36
37 monkeys[monkeyNumber].test = (() => {
38 const divisibleBy = +data[i + 3].replace("Test: divisible by ", "").trim()
39 const destMonkeyIfTrue = +data[i + 4]
40 .replace("If true: throw to monkey ", "")
41 .trim()
42 const destMonkeyIfFalse = +data[i + 5]
43 .replace("If false: throw to monkey ", "")
44 .trim()
45
46 return {
47 fn: x => x % divisibleBy === 0,
48 destMonkeys: [destMonkeyIfFalse, destMonkeyIfTrue],
49 }
50 })()
51
52 monkeys[monkeyNumber].itemsInspectedTimes = 0
53 }
54
55 return Object.values(monkeys)
56}
57
58const main = () => {
59 const monkeys = readData()
60
61 let numberOfRounds = 20
62
63 while (numberOfRounds--) {
64 for (const [monkeyNo, monkey] of Object.entries(monkeys)) {
65 for (let itemIndex = 0; itemIndex < monkey.items.length; itemIndex++) {
66 const item = monkey.items[itemIndex]
67 let worryLevel = monkey.op(item)
68 worryLevel = Math.floor(worryLevel / 3)
69 const destMonkey = monkey.test.destMonkeys[+monkey.test.fn(worryLevel)]
70 monkeys[monkeyNo].items.splice(itemIndex, 1)
71 itemIndex--
72 monkeys[monkeyNo].itemsInspectedTimes++
73 monkeys[destMonkey].items.push(worryLevel)
74 }
75 }
76 }
77
78 const res = monkeys
79 .map(({ itemsInspectedTimes }) => itemsInspectedTimes)
80 .sort((a, b) => b - a)
81 .slice(0, 2)
82 .reduce((acc, el) => acc * el, 1)
83
84 console.log(res)
85}
86
87main()

Part 2

Use modulo operation to avoid number explosion (BigInt)

I'm suck at math so I borrowed the solution and leave some others' comments as references below:

  • Comment 1
  • Comment 2

Implementation

1const fs = require("fs")
2
3const readData = () => {
4 const data = fs
5 .readFileSync("./input", "utf-8")
6 .split(/\r?\n/)
7 .filter(Boolean)
8
9 const monkeys = {}
10
11 for (let i = 0; i < data.length; i += 6) {
12 const monkeyNumber = i / 6
13 monkeys[monkeyNumber] = {}
14 monkeys[monkeyNumber].items = data[i + 1]
15 .replace("Starting items: ", "")
16 .trim()
17 .replace(/,/g, "")
18 .split(" ")
19 .map(Number)
20
21 monkeys[monkeyNumber].op = (() => {
22 const [operator, operand2] = data[i + 2]
23 .replace("Operation: new = old ", "")
24 .trim()
25 .split(" ")
26
27 const isMirror = operand2 === "old"
28
29 return {
30 "+": (operand, isMirror) => x => x + (isMirror ? x : operand),
31 "-": (operand, isMirror) => x => x - (isMirror ? x : operand),
32 "*": (operand, isMirror) => x => x * (isMirror ? x : operand),
33 "/": (operand, isMirror) => x => x / (isMirror ? x : operand),
34 }[operator](+operand2, isMirror)
35 })()
36
37 monkeys[monkeyNumber].test = (() => {
38 const divisibleBy = +data[i + 3].replace("Test: divisible by ", "").trim()
39 const destMonkeyIfTrue = +data[i + 4]
40 .replace("If true: throw to monkey ", "")
41 .trim()
42 const destMonkeyIfFalse = +data[i + 5]
43 .replace("If false: throw to monkey ", "")
44 .trim()
45
46 return {
47 divisibleBy,
48 fn: x => x % divisibleBy === 0,
49 destMonkeys: [destMonkeyIfFalse, destMonkeyIfTrue],
50 }
51 })()
52
53 monkeys[monkeyNumber].itemsInspectedTimes = 0
54 }
55
56 return Object.values(monkeys)
57}
58
59const main = () => {
60 const monkeys = readData()
61
62 let numberOfRounds = 10000
63
64 const modulo = monkeys
65 .map(({ test: { divisibleBy } }) => divisibleBy)
66 .reduce((acc, el) => acc * el, 1)
67
68 while (numberOfRounds--) {
69 for (const [monkeyNo, monkey] of Object.entries(monkeys)) {
70 monkey.itemsInspectedTimes += monkey.items.length
71 for (let itemIndex = 0; itemIndex < monkey.items.length; itemIndex++) {
72 const item = monkey.items[itemIndex]
73 let worryLevel = monkey.op(item)
74 worryLevel = worryLevel % modulo
75 const destMonkey = monkey.test.destMonkeys[+monkey.test.fn(worryLevel)]
76 monkeys[monkeyNo].items.splice(itemIndex, 1)
77 itemIndex--
78 monkeys[destMonkey].items.push(worryLevel)
79 }
80 }
81 }
82
83 const res = monkeys
84 .map(({ itemsInspectedTimes }) => itemsInspectedTimes)
85 .sort((a, b) => b - a)
86 .slice(0, 2)
87 .reduce((acc, el) => acc * el, 1)
88
89 console.log(res)
90}
91
92main()

References

Original problem

Comments

Loading comments...

Tags

adventofcode

math

Next Post

Advent of Code 2022 - Day 12: Hill Climbing Algorithm

Dec 12, 2022

BFS

Previous Post

Advent of Code 2022 - Day 10: Cathode-Ray Tube

Dec 10, 2022

A creative challenge

HoningJS

Search Posts