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 ];