Skip to content

Instantly share code, notes, and snippets.

@polettix
Created December 17, 2020 18:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save polettix/831c8af2fbb30bfdd7beb9433b7d7709 to your computer and use it in GitHub Desktop.
Save polettix/831c8af2fbb30bfdd7beb9433b7d7709 to your computer and use it in GitHub Desktop.
#!/usr/bin/env perl
use 5.024;
use warnings;
use English qw< -no_match_vars >;
use autodie;
use experimental qw< postderef signatures >;
no warnings qw< experimental::postderef experimental::signatures >;
use File::Basename qw< basename >;
use Data::Dumper; $Data::Dumper::Indent = 1;
use Storable 'dclone';
$|++;
my @active;
my $filename = shift || basename(__FILE__) =~ s{\.pl\z}{.input}rmxs;
open my $fh, '<', $filename;
my $x = 0;
while (<$fh>) {
my @line = split m{\s*}mxs;
for my $y (0 .. $#line) {
push @active, "$x $y 0" if $line[$y] eq '#';
}
++$x;
}
say join ' / ', @active;
my $state = \@active;
for (1 .. 6) {
$state = conway_3d_tick($state);
say join ' / ', $state->@*;
}
say scalar $state->@*;
# move to 4 dimensions
$_ .= ' 0' for @active;
$state = \@active;
$state = conway_4d_tick($state) for 1 .. 6;
say scalar $state->@*;
# returns new state
sub conway_3d_tick ($state) {
my %previously_active;
my %count_for;
for my $cell ($state->@*) {
my ($x, $y, $z) = split m{\s+}mxs, $cell;
for my $xd (-1 .. 1) {
my $X = $x + $xd;
for my $yd (-1 .. 1) {
my $Y = $y + $yd;
for my $zd (-1 .. 1) {
my $Z = $z + $zd;
my $key = "$X $Y $Z";
if ($xd == 0 && $yd == 0 && $zd == 0) {
$previously_active{$key} = 1;
}
else {
$count_for{$key}++;
}
}
}
}
}
my @active;
while (my ($key, $count) = each %count_for) {
if ($previously_active{$key}) {
push @active, $key if $count == 2 || $count == 3;
}
else {
push @active, $key if $count == 3;
}
}
return \@active;
}
# returns new state
sub conway_4d_tick ($state) {
my %previously_active;
my %count_for;
for my $cell ($state->@*) {
my ($x, $y, $z, $w) = split m{\s+}mxs, $cell;
for my $wd (-1 .. 1) {
my $W = $w + $wd;
for my $xd (-1 .. 1) {
my $X = $x + $xd;
for my $yd (-1 .. 1) {
my $Y = $y + $yd;
for my $zd (-1 .. 1) {
my $Z = $z + $zd;
my $key = "$X $Y $Z $W";
if ($xd == 0 && $yd == 0 && $zd == 0 && $wd == 0) {
$previously_active{$key} = 1;
}
else {
$count_for{$key}++;
}
}
}
}
}
}
my @active;
while (my ($key, $count) = each %count_for) {
if ($previously_active{$key}) {
push @active, $key if $count == 2 || $count == 3;
}
else {
push @active, $key if $count == 3;
}
}
return \@active;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment