day11-2.pl (3199B) - raw
1 #!/usr/bin/env perl 2 3 use strict; 4 use warnings; 5 use v5.22; 6 7 # Day 11, Part 2 8 9 use constant FLASH_LIMIT => 9; 10 use constant POPULATION => 100; 11 12 sub get_filehandle { 13 if (@ARGV !=1) { 14 die "Usage: $0 [input-filename]"; 15 } 16 my $input_filename = $ARGV[0]; 17 open my $filehandle, '<', $input_filename or 18 die "Could not open input file $input_filename: $!"; 19 return $filehandle; 20 } 21 22 sub print_octopuses { # for debugging purposes 23 my ($oct_ref, $rows, $columns) = @_; 24 my @octopuses = @{$oct_ref}; 25 foreach my $row (0 .. $rows - 2) { 26 foreach my $column (0 .. $columns - 2) { 27 print $octopuses[$row][$column]; 28 } 29 print "\n"; 30 } 31 print "\n"; 32 } 33 34 my $filehandle = get_filehandle(); 35 # add extra column of negative infinity 36 my @octopuses = map{ [m/\d/g, "-inf"] } <$filehandle>; 37 my $columns = @{$octopuses[0]}; 38 # add extra row of negative infinity 39 push @octopuses => [ ("-inf") x $columns ]; 40 my $rows = @octopuses; 41 my @neighbors; 42 foreach my $nr (-1 .. 1) { 43 foreach my $nc (-1 .. 1) { 44 push @neighbors => [$nr, $nc] unless ($nr == 0 && $nc == 0); 45 } 46 } 47 my $flash_count = 0; 48 my $count_on = 0; 49 my $step; 50 51 while ($count_on != POPULATION) { 52 $step++; 53 my @queue = (); 54 my %flash_state = (); 55 # 10 iterate through each octopus and increment its counter by 1 56 foreach my $row (0 .. $rows - 2) { 57 foreach my $column (0 .. $columns - 2) { 58 $octopuses[$row][$column]++; 59 # 20 iterate through each octopus and see whether its energy level 60 # is greater than 9 61 if ($octopuses[$row][$column] > FLASH_LIMIT && 62 !exists $flash_state{$row, $column}) { 63 # 30 for any octupus whose energy level is greater than 9 AND which 64 # has not yet flashed in this step: 65 # - update its state in a hash indicating that it has flashed 66 # - increment the flash counter 67 # - add its position to a queue which we will iterate through to 68 # increase the energy level of adjacent octupuses 69 $flash_state{$row, $column} = 1; 70 $flash_count++; 71 push @queue => [ $row, $column ]; 72 } 73 } 74 } 75 while (@queue) { 76 my $octopus = shift @queue; 77 my $r = $octopus->[0]; 78 my $c = $octopus->[1]; 79 foreach my $neighbor (@neighbors) { 80 my $neighbor_row = $r + $neighbor->[0]; 81 my $neighbor_col = $c + $neighbor->[1]; 82 $octopuses[$neighbor_row][$neighbor_col]++; 83 if ($octopuses[$neighbor_row][$neighbor_col] > FLASH_LIMIT && 84 !exists $flash_state{$neighbor_row, $neighbor_col}) { 85 $flash_state{$neighbor_row, $neighbor_col} = 1; 86 $flash_count++; 87 push @queue => [ $neighbor_row, $neighbor_col ]; 88 } 89 } 90 } 91 $count_on = 0; 92 foreach my $row (0 .. $rows -2) { 93 foreach my $column (0 .. $columns - 2) { 94 if (exists $flash_state{$row, $column} && 95 $flash_state{$row, $column} == 1) { 96 $octopuses[$row][$column] = 0; 97 $count_on++; 98 } 99 } 100 } 101 } 102 103 say "part 2: after step $step, all octopuses flashed";