Day18.pm (3409B) - raw
1 package Day18; 2 3 use strict; 4 use warnings; 5 use v5.32; 6 use Exporter qw( import ); 7 8 our @EXPORT = qw( init_lights flash_lights display_lights count_lights ); 9 10 sub setup_neighbors 11 { 12 my @neighbors; 13 foreach my $nr (-1 .. 1) { 14 foreach my $nc (-1 .. 1) { 15 push @neighbors => [$nr, $nc] unless ($nr == 0 && $nc == 0); 16 } 17 } 18 return \@neighbors; 19 } 20 21 sub init_lights 22 { 23 my @lights; 24 25 # Define array @lights to hold initial state of lighting configuration. 26 # Input to subroutine is string which contains puzzle input. This string 27 # also contains mulitple end of line separators ( \n ). Break up each 28 # line using split // into an array. Pad the array with a trailing 0 to 29 # serve as a boundary when we iterate through the array later on. We do 30 # this by taking advantage that the -1 index ( $lights[ -1 ] ) refers to 31 # the last element in the array. This is important when doing comparisons 32 # on the first element of the array as we will wrap back to the last 33 # element which is just the extra padding. 34 push @lights => [ ( split // ), '.' ] foreach ( split /\n/, shift ); 35 36 # Add an extra row at the end to serve as a boundary when we do the neighbor 37 # comparisons later on. 38 push @lights => [ ('.') x scalar @{ $lights[0] } ]; 39 return \@lights; 40 } 41 42 sub update_light 43 { 44 my $row = shift; 45 my $col = shift; 46 my @lights = @{ shift() }; 47 my @neighbors = @{ setup_neighbors() }; 48 my $neighbors_on = 0; 49 foreach my $neighbor ( @neighbors ) { 50 my $neighbor_row = $row + $neighbor->[0]; 51 my $neighbor_col = $col + $neighbor->[1]; 52 $neighbors_on++ if ( $lights[ $neighbor_row ][ $neighbor_col ] eq '#' ); 53 } 54 if ( $lights[ $row ][ $col ] eq '#' ) { 55 return ( $neighbors_on == 2 || $neighbors_on == 3 ) ? '#' : '.'; 56 } else { 57 return ( $neighbors_on == 3 ) ? '#' : '.'; 58 } 59 } 60 61 sub flash_lights 62 { 63 my $current_state = shift; 64 my $part = shift; 65 # need to declare a clean, new array, completely separate from $current_state 66 # so as not to alter the current state when updating the new state 67 my @next_state; 68 my $rows = scalar @{ $current_state }; 69 my $columns = scalar @{ $current_state->[ 0 ] }; 70 foreach my $row ( 0 .. $rows - 2 ) { 71 foreach my $col ( 0 .. $columns - 2 ) { 72 if ( 73 ( $part == 2 ) && 74 ( $row == 0 && $col == 0 || 75 $row == 0 && $col == $columns - 2 || 76 $row == $rows - 2 && $col == 0 || 77 $row == $rows - 2 && $col == $columns - 2 ) 78 ) { 79 $next_state[ $row ][ $col ] = '#'; 80 } else { 81 $next_state[ $row ][ $col ] = update_light( $row, $col, $current_state ); 82 } 83 } 84 push @{ $next_state[ $row ] } => '.'; # add trailing column back in 85 } 86 push @next_state => [ ('.') x $columns ]; # add trailing row back in 87 88 return \@next_state; 89 } 90 91 sub display_lights # for debugging purposes only 92 { 93 say "@{ $_ }" foreach ( @{ shift() } ); 94 } 95 96 sub count_lights 97 { 98 my $lights = shift; 99 my $count = 0; 100 foreach my $row ( @{ $lights } ) { 101 foreach my $col ( @{ $row } ) { 102 $count++ if ( $col eq '#' ); 103 } 104 } 105 return $count; 106 } 107 108 1;