DEV Community

Cover image for Monkey in the Middle
Robert Mion
Robert Mion

Posted on

Monkey in the Middle

Advent of Code 2022 Day 11

Part 1

  1. Ugh, this kind of puzzle again?
  2. Planning my data structures
  3. Skipping input parsing
  4. My algorithm in JavaScript in stages

Ugh, this kind of puzzle again?

You know the kind:

  • Several players
  • Multiple rounds
  • Lots of player attributes to track
  • Attributes of multiple players changing multiple times in a single round

It will likely require:

  • Multiple collections of dictionaries (array of objects in JavaScript)
  • Multiple properties
  • Some being methods, some being arrays
  • Lots of re-checking the puzzle explanations
  • Lots of trial and error
  • Lots of patience

Hopefully I can earn at least one star when this is all done.

But prior disappointments have me feeling not too confident.

Still, I'm excited to get to work!

Planning my data structures

Referring to the first monkey in the example input:

Monkey 0:
  Starting items: 79, 98
  Operation: new = old * 19
  Test: divisible by 23
    If true: throw to monkey 2
    If false: throw to monkey 3
Enter fullscreen mode Exit fullscreen mode

I need a list of monkeys:

[
  { },
  { },
  ...
]
Enter fullscreen mode Exit fullscreen mode

Monkey 0 has three properties:

{
  items: ...,
  operation: ...,
  test: ...
}
Enter fullscreen mode Exit fullscreen mode

items is an array:

  items: [79, 98]
Enter fullscreen mode Exit fullscreen mode

operation is a function that works with each number in items:

  operation: (index) => {
    let new = items[index] * 19
    new = Math.floor(new / 3)
    items[index] = new
  }
Enter fullscreen mode Exit fullscreen mode

test is a function that works with each updated number in items:

  test: (index) => {
    let item = items.splice(index, 1)
    if (item % 23 == 0) {
      monkeys[1].items.push(item)
    } else {
      monkeys[2].items.push(item)
    }    
  }
Enter fullscreen mode Exit fullscreen mode

I foresee needing to edit each property and method due to misreading the instructions.

Now for the tracker of each monkey's number of inspected items.

At the end of each round, I need to tally up each monkeys number of inspected items.

In the example, there are four monkeys:

[0, 0, 0, 0]
Enter fullscreen mode Exit fullscreen mode

At the end of round 1, these are each monkey's items:

Monkey 0: 20, 23, 27, 26
Monkey 1: 2080, 25, 167, 207, 401, 1046
Monkey 2: 
Monkey 3:
Enter fullscreen mode Exit fullscreen mode

So this needs to be my tally:

[4, 6, 0, 0]
Enter fullscreen mode Exit fullscreen mode

I think I just need to increment each amount by the length of each monkey's items.

Hopefully it ends up being that simple.

Skipping input parsing

  • This puzzle's input would require a lot of code to parse into the data structure I outlined above
  • I'm confident I could do it, but am more interested in writing an algorithm that plays each round than I am in parsing the input
  • I don't intend to build a simulator for this puzzle, mostly because I still have doubts that I'll solve Part 1 let alone Part 2
  • Therefore, I'll manually build my monkeys array

My algorithm in JavaScript in stages

Monkey 0 in my monkeys array:

{
  items: [79, 98],
  operation() {
    let now = this.items[0] * 19
    now = Math.floor(next / 3)
    this.items[0] = now
    this.test()
  },
  test() {
    let item = this.items.shift()
    if (item % 23 == 0) {
      monkeys[2].items.push(item)
    } else {
      monkeys[3].items.push(item)
    }    
  }
}
Enter fullscreen mode Exit fullscreen mode

Issues I overlooked when writing the object above:

  • Having to remove each item after passing it to another monkey
  • Avoiding use of the keyword new
  • Using this in each method

I store the count of each monkey's inspected items as:

let times = [0,0,0,0]
Enter fullscreen mode Exit fullscreen mode

Each round of Keep Away is represented as:

for (let m = 0; m < monkeys.length; m++) {
  times[m] += monkeys[m].items.length
  while (monkeys[m].items.length) {
    monkeys[m].operation()
  }
}
Enter fullscreen mode Exit fullscreen mode

Finally, I calculate the product of the two largest counts:

times
    .sort((a, b) => b - a)
    .slice(0, 2)
    .reduce((product, count) => product * count)
Enter fullscreen mode Exit fullscreen mode

It works on the example input.

Will it work on my puzzle input?

...

Too high.

With manual entry of data comes high likelihood for errors.

Did I mis-enter some number?

Yes. Yes I did.

Will it work now?

Correct answer!

Part 2

Confused and thus prohibited

  • I understand that I no longer need to divide and round down
  • But after removing that line from each monkey in my example input and processing 20 rounds, I get three correct amounts and one amount that is two higher than expected
  • Since the example tests go from 1 to 20, I can't easily confirm where my algorithm is going wrong
  • Plus, I honestly don't know another way to manage my relief so that I could run all 10000 rounds

So, sadly, I don't think I'll be earning this second star.

I did it!

  • I solved Part 1!
  • By troubleshooting my way through writing a working data structure, loop and fixing data that I manually entered!

I have a poor track record with Part 2's that are performance tests.

Even if I wanted to run my algorithm and hope that it eventually processes all 10000 rounds, I'm sure it wouldn't generate the correct answer since it didn't work on 20 rounds of the example input.

Nonetheless, I'm proud that I earned one star.

Top comments (0)