aoc2022

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

day11.pl (4255B) - 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      = 20;
     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 foreach my $round ( 1 .. $ROUNDS ) {
     64     my $num = 0;
     65     foreach my $monkey ( @monkeys1 ) {
     66         $logger->trace( "Monkey $num:" );
     67         while ( @{ $monkey->{ $ITEMS } } ) {
     68             my $item = shift @{ $monkey->{ $ITEMS } };
     69             $logger->trace( "  Monkey inspects an item with a worry level of $item." );
     70             $monkeys1_count{ $num }++;
     71             my $expression = join " ",
     72                              $item,
     73                              $monkey->{ $OPERATION }{ operation },
     74                              $monkey->{ $OPERATION }{ operand   } eq 'old' ? $item :
     75                              $monkey->{ $OPERATION }{ operand   };
     76             $item = eval $expression;
     77             $logger->trace( "    Worry level is now $item." );
     78             $item = int( $item / 3 );
     79             $logger->trace("    Monkey gets bored with item. ",
     80                            "Worry level is divided by 3 to $item.");
     81             if ( $item % $monkey->{ $TEST } == 0 ) { # true
     82                 $logger->trace( "    Current worry level is divisible by ",
     83                                 "$monkey->{ $TEST }." );
     84                 $logger->trace( "    Item with worry level $item is thrown to monkey ",
     85                                 "$monkey->{ $TRUE }." );
     86                 push @{ $monkeys1[ $monkey->{ $TRUE } ]->{ $ITEMS } } => $item;
     87             } else { # false
     88                 $logger->trace( "    Current worry level is not divisible by ",
     89                                 "$monkey->{ $TEST }." );
     90                 $logger->trace( "    Item with worry level $item is thrown to monkey ",
     91                                 "$monkey->{ $FALSE }." );
     92                 push @{ $monkeys1[ $monkey->{ $FALSE } ]->{ $ITEMS } } => $item;
     93             }
     94         }
     95         $num++;
     96     }
     97 
     98     $logger->debug( "After round $round, the monkeys are holding items with these ",
     99                     "worry levels:" );
    100     foreach my $i ( 0 .. $#monkeys1 ) {
    101         $logger->debug( "Monkey $i: ",
    102                         ( join ", ", @{ $monkeys1[ $i ]->{ $ITEMS } } ) );
    103     }
    104 }
    105 
    106 foreach my $monkey ( sort keys %monkeys1_count ) {
    107     $logger->info( "Monkey $monkey inspected items $monkeys1_count{ $monkey } times." );
    108 }
    109 
    110 my @inspections = reverse( sort { $a <=> $b } ( values %monkeys1_count ) );
    111 say "part 1: ", product @inspections[ 0 .. 1 ];