package Day18; use strict; use warnings; use v5.32; use Exporter qw( import ); our @EXPORT = qw( init_lights flash_lights display_lights count_lights ); sub setup_neighbors { my @neighbors; foreach my $nr (-1 .. 1) { foreach my $nc (-1 .. 1) { push @neighbors => [$nr, $nc] unless ($nr == 0 && $nc == 0); } } return \@neighbors; } sub init_lights { my @lights; # Define array @lights to hold initial state of lighting configuration. # Input to subroutine is string which contains puzzle input. This string # also contains mulitple end of line separators ( \n ). Break up each # line using split // into an array. Pad the array with a trailing 0 to # serve as a boundary when we iterate through the array later on. We do # this by taking advantage that the -1 index ( $lights[ -1 ] ) refers to # the last element in the array. This is important when doing comparisons # on the first element of the array as we will wrap back to the last # element which is just the extra padding. push @lights => [ ( split // ), '.' ] foreach ( split /\n/, shift ); # Add an extra row at the end to serve as a boundary when we do the neighbor # comparisons later on. push @lights => [ ('.') x scalar @{ $lights[0] } ]; return \@lights; } sub update_light { my $row = shift; my $col = shift; my @lights = @{ shift() }; my @neighbors = @{ setup_neighbors() }; my $neighbors_on = 0; foreach my $neighbor ( @neighbors ) { my $neighbor_row = $row + $neighbor->[0]; my $neighbor_col = $col + $neighbor->[1]; $neighbors_on++ if ( $lights[ $neighbor_row ][ $neighbor_col ] eq '#' ); } if ( $lights[ $row ][ $col ] eq '#' ) { return ( $neighbors_on == 2 || $neighbors_on == 3 ) ? '#' : '.'; } else { return ( $neighbors_on == 3 ) ? '#' : '.'; } } sub flash_lights { my $current_state = shift; my $part = shift; # need to declare a clean, new array, completely separate from $current_state # so as not to alter the current state when updating the new state my @next_state; my $rows = scalar @{ $current_state }; my $columns = scalar @{ $current_state->[ 0 ] }; foreach my $row ( 0 .. $rows - 2 ) { foreach my $col ( 0 .. $columns - 2 ) { if ( ( $part == 2 ) && ( $row == 0 && $col == 0 || $row == 0 && $col == $columns - 2 || $row == $rows - 2 && $col == 0 || $row == $rows - 2 && $col == $columns - 2 ) ) { $next_state[ $row ][ $col ] = '#'; } else { $next_state[ $row ][ $col ] = update_light( $row, $col, $current_state ); } } push @{ $next_state[ $row ] } => '.'; # add trailing column back in } push @next_state => [ ('.') x $columns ]; # add trailing row back in return \@next_state; } sub display_lights # for debugging purposes only { say "@{ $_ }" foreach ( @{ shift() } ); } sub count_lights { my $lights = shift; my $count = 0; foreach my $row ( @{ $lights } ) { foreach my $col ( @{ $row } ) { $count++ if ( $col eq '#' ); } } return $count; } 1;