aoc2022

Advent of Code 2022 solutions in Perl.
git clone git://git.samirparikh.com/aoc2022
Log | Files | Refs | README

day11.2.pl (4401B) - raw


      1 #!/usr/local/bin/perl
      2 # day 2022-11
      3 
      4 use strict;
      5 use warnings;
      6 use v5.32;
      7 
      8 use List::Util qw( product );
      9 
     10 use Log::Log4perl ();
     11 use Log::Log4perl::Level ();
     12 Log::Log4perl->easy_init(
     13     Log::Log4perl::Level::to_priority( 'OFF' )
     14 ); # set to 'OFF', 'INFO', 'DEBUG' or 'TRACE'  for successively more information
     15 my $logger = Log::Log4perl->get_logger();
     16 
     17 @ARGV = "input" unless @ARGV;
     18 $/ = ''; # set to paragraph mode.  Each monkey is treated as one record
     19 my @input = <>;
     20 
     21 my $ITEMS       = "items";
     22 my $OPERATION   = "Operation";
     23 my $TEST        = "Test";
     24 my $TRUE        = "true";
     25 my $FALSE       = "false";
     26 my $ROUNDS      = 10000;
     27 
     28 sub init_monkeys {
     29     my @input = @_;
     30     my @monkeys;
     31     foreach my $monkey ( @input ) {
     32         my %monkey;
     33         foreach my $attribute ( split /\n/, $monkey ) {
     34             next if ( $attribute =~ m/Monkey/ );
     35             my ( $key, $value ) = split /:/ => $attribute;
     36             if ( $key =~ m/$ITEMS/ ) {
     37                 $value =~ s/\s//g;
     38                 $monkey{ $ITEMS } = [ split /,/ => $value ];
     39             } elsif ( $key =~ m/$OPERATION/ ) {
     40                 my %operation;
     41                 my ( $operation, $operand ) = $value =~ m/(\+|\*) (.+)/;
     42                 $monkey{ $OPERATION } = { "operation" => $operation,
     43                                           "operand"   => $operand,
     44                                         };
     45             } elsif ( $key =~ m/$TEST/ ) {
     46                 ( $monkey{ $TEST } )  = $value =~ m/(\d+)/;
     47             } elsif ( $key =~ m/$TRUE/ ) {
     48                 ( $monkey{ $TRUE } )  = $value =~ m/(\d+)/;
     49             } elsif ( $key =~ m/$FALSE/ ) {
     50                 ( $monkey{ $FALSE } ) = $value =~ m/(\d+)/;
     51             } else {
     52                 die "Could not parse attribute $attribute";
     53             }
     54         }
     55         push @monkeys => \%monkey;
     56     }
     57     return @monkeys;
     58 }
     59 
     60 my @monkeys1 = init_monkeys( @input );
     61 my %monkeys1_count;
     62 
     63 my $modulo = 1;
     64 $modulo *= $_->{ $TEST } foreach ( @monkeys1 );
     65 $logger->trace( "modulo = $modulo" );
     66 
     67 foreach my $round ( 1 .. $ROUNDS ) {
     68     my $num = 0;
     69     foreach my $monkey ( @monkeys1 ) {
     70         $logger->trace( "Monkey $num:" );
     71         while ( @{ $monkey->{ $ITEMS } } ) {
     72             my $item = shift @{ $monkey->{ $ITEMS } };
     73             $logger->trace( "  Monkey inspects an item with a worry level of $item." );
     74             $monkeys1_count{ $num }++;
     75             my $expression = join " ",
     76                              $item,
     77                              $monkey->{ $OPERATION }{ operation },
     78                              $monkey->{ $OPERATION }{ operand   } eq 'old' ? $item :
     79                              $monkey->{ $OPERATION }{ operand   };
     80             $item = eval $expression;
     81             $item = $item % $modulo;
     82             $logger->trace( "    Worry level is now $item." );
     83             #$item = int( $item / 3 );
     84             #$logger->trace("    Monkey gets bored with item. ",
     85             #               "Worry level is divided by 3 to $item.");
     86             if ( $item % $monkey->{ $TEST } == 0 ) { # true
     87                 $logger->trace( "    Current worry level is divisible by ",
     88                                 "$monkey->{ $TEST }." );
     89                 $logger->trace( "    Item with worry level $item is thrown to monkey ",
     90                                 "$monkey->{ $TRUE }." );
     91                 push @{ $monkeys1[ $monkey->{ $TRUE } ]->{ $ITEMS } } => $item;
     92             } else { # false
     93                 $logger->trace( "    Current worry level is not divisible by ",
     94                                 "$monkey->{ $TEST }." );
     95                 $logger->trace( "    Item with worry level $item is thrown to monkey ",
     96                                 "$monkey->{ $FALSE }." );
     97                 push @{ $monkeys1[ $monkey->{ $FALSE } ]->{ $ITEMS } } => $item;
     98             }
     99         }
    100         $num++;
    101     }
    102 
    103     $logger->debug( "After round $round, the monkeys are holding items with these ",
    104                     "worry levels:" );
    105     foreach my $i ( 0 .. $#monkeys1 ) {
    106         $logger->debug( "Monkey $i: ",
    107                         ( join ", ", @{ $monkeys1[ $i ]->{ $ITEMS } } ) );
    108     }
    109 }
    110 
    111 foreach my $monkey ( sort keys %monkeys1_count ) {
    112     $logger->info( "Monkey $monkey inspected items $monkeys1_count{ $monkey } times." );
    113 }
    114 
    115 my @inspections = reverse( sort { $a <=> $b } ( values %monkeys1_count ) );
    116 say "part 2: ", product @inspections[ 0 .. 1 ];