#!/usr/bin/env perl
use strict;
use warnings;

use Storable qw(dclone);

# Read in the grid
# TRICK: to make neighbors easier, pad by '.' on all ends
my @G;
my $i = 0;
while (<ARGV>) {
    chomp;
    $G[$i] = ['.', split('', $_), '.'];
    $i++;
}
push(@G, [('.') x scalar @{$G[0]}]);
unshift(@G, [('.') x scalar @{$G[0]}]);

$i = 0;
while (evolve(\@G)) {
    print "Evolving ... $i\n";
    $i++;
}

my $total = 0;
for my $r (@G) {
    $total += scalar grep { $_ eq '#' } @$r;
}
print "$total\n";

sub evolve {
    my ($G) = @_;
    # 1. deep clone
    # 2. for loop over grid, change (mark did_change)
    # 3. return did_change
    my $orig = dclone($G);
    my $did_change;

    my $R = scalar @$orig;
    my $C = scalar @{$orig->[0]};
    for (my $i = 1; $i < $R - 1; $i++) {
        for (my $j = 1; $j < $C - 1; $j++) {
            my $seat = $orig->[$i]->[$j];
            next if $seat eq '.'; # floor don't change
            
            # neighbors...
            my @neighs = map { $orig->[$_->[0]]->[$_->[1]] } (
                [$i - 1, $j - 1],
                [$i - 1, $j],
                [$i - 1, $j + 1],
                [$i, $j - 1],
                #[$i, $j], <-- don't include self
                [$i, $j + 1],
                [$i + 1, $j - 1],
                [$i + 1, $j],
                [$i + 1, $j + 1],
            );
            my $num_occ = scalar grep { $_ eq '#' } @neighs;

            if ($seat eq 'L' && $num_occ == 0) {
                $G->[$i]->[$j] = '#';
                $did_change = 1;
            } elsif ($seat eq '#' && $num_occ >= 4) {
                $G->[$i]->[$j] = 'L';
                $did_change = 1;
            }
        }
    }

    return $did_change;;
}
