2022 Day 11: Monkey in the Middle

Spent a huge amount of time to understand why Ada.Integer_Text_IO.Get is unable to read a value from 0: string :rage:. As always I forgot about deprecated integer format, where # could b replaced by :. Isn’t time to get rid of this in 2022? :slightly_frowning_face:



I missed that banana skin by chance (or by being lazy ?): I have assumed that the monkeys are ordered, so the parser skips that line completely (source here).


Wow. For once I didnt bother with parsing input; it was short, so I said to myself, “Let’s include it directly.” I later wondered whether that was a good idea, but seeing your post, maybe so!

As a mathematician I’m embarrassed to confess that my stumbling block was not noticing that part 2 simply requires modular arithmetic, so I wasted far too much time re-learning the Big_Integer crate, which turned out to be too small anyway!


I also spent some time at this point, and opted to assume that there are no more than 9 moneys: read a Character and converted to Natural :stuck_out_tongue:

1 Like

That’s curious; I had seven. Do people mind saying how many they had?

  • I had…
  • 6 or fewer monkeys
  • 7 monkeys
  • 8 monkeys
  • 9 monkeys
  • 10 or more monkeys

0 voters

(After seeing that someone else had 8, I went back and checked and realized I actually had 8: monkeys 0 through 7. Duh! I can’t even blame it on a lack of caffeine.)

later OK, I thought we’d see some variety here, but apparently I both misunderstood @rocher’s message and misremembered my own input. I guess everyone has 8.

I have considered that way seriously, but for some reason I wanted to solve the problem with HAC which hasn’t aggregates, so I went for a parser for which there is a draft that can be easily adapted. Later I’ve realized that HAT (HAC’s embedded toolbox package) didn’t have a Delete procedure for removing a part of a variable-size string. This shocking omission is fixed now :relieved:.

1 Like

Can you explain what do you and @cantanima mean with “Let’s include it directly”?

Sure! Let me know if this isn’t enough.

   Monkeys: Monkey_Array
   -- transcribing this might not be the best idea I ever had,
   -- but it saved me the trouble of writing a parser
      := ( if Doing_Example then (
           0 => (
                 Items           => ( 79, 98, others => 0 ),
                 Next_Free       => 3,
                 Operation       => Multiply,
                 Operand         => 19,
                 Test            => 23,
                 Dest_True       => 2,
                 Dest_False      => 3,
                 Items_Inspected => 0
           1 => (
                 Items           => ( 54, 65, 75, 74, others => 0 ),
                 Next_Free       => 5,

So Monkey 0 has items 79 and 98; your interest is multiplied by 19 when he inspects an item, he tests your interest by dividing by 23; if divisible, he sends it to Monkey 2; otherwise, to Monkey 3, and at the outset has inspected 0 items.

This is the first example monkey; the puzzle monkeys were defined in the else clause.

1 Like

Oh! Yes, I see, thanks … and when Operand = 0, then use the old value, right? Or did you define a type to support Natural and "old"?

I think he has a proper operation (Square) for the old * old case:

type Worry_Change is ( Add, Multiply, Square );
1 Like

As @zertovitch points out, I defined a proper operation Square, and in that case the “processor” ignores the value of Operand. I didn’t think at the time about making a discriminated record, the way someone else who also defined an enumeration did. I should have done that, and if I go revise my solution I probably will. I was thinking of adding a parser, anyway.

I’m not a mathematician, but I have a quite good background on math. I had the intuition that new Worry_Level that results from a Monkey inspection can be transformed modulo the LCM (least common multiple) of all division test numbers the troop is using. So before throwing the item I applied this operation … and it worked! But I don’t remember which is the number property or theorem for a good explanation to be based on. I simply thought that “anything that happens with Items in [0, N] (N=LCM-1) is also happening in [k*N, (k+1)*N]”. Is there a better explanation? or, Is there a better way to solve this puzzle?

hmmm … there is no old + old case??

I think you were actually thinking the converse; that is, “anything that happens with Items in [k*N, (k+1)*N] (N=LCM-1) is also happening in [0, N]”.

That’s essentially the idea, adding the caveat that “anything” (a very broad term) might not happen in the more general case where the divisibility involves numbers that are not relatively prime to each other. For example.

I didn’t have one. Did you? I only had old * old.

No, I wasn’t :stuck_out_tongue: My analysis was more basic and was like Item values are quite low at the beginning, so there must be a way to keep them low modulo something in the next iterations; to keep them in [0,N], and because all monkeys are making divisibility tests, what about the LCM of them all?” … again, that was an intuition, not a mathematical reasoning :rofl:

Thanks for the link, didn’t remember that theorem, neither know its extension to co-prime numbers … I didn’t notice that the test numbers used by monkeys are all primes.

Regarding the old + old case, I did an implementation that supports it, just is case …