]> www.fi.muni.cz Git - aoc.git/commitdiff
Day 22: slow but straightforward. off-by-three errors.
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Sun, 24 Dec 2023 08:23:38 +0000 (09:23 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Sun, 24 Dec 2023 08:23:38 +0000 (09:23 +0100)
2023/43.pl [new file with mode: 0755]
2023/44.pl [new file with mode: 0755]

diff --git a/2023/43.pl b/2023/43.pl
new file mode 100755 (executable)
index 0000000..da408f2
--- /dev/null
@@ -0,0 +1,91 @@
+#!/usr/bin/perl -w
+
+use v5.38;
+use experimental 'multidimensional';
+
+my @bricks = map { [ /\d+/g ] } <>;
+my %seen;
+sub set_brick {
+       my ($b) = @_;
+
+       for my $x ($b->[0] .. $b->[3]) {
+       for my $y ($b->[1] .. $b->[4]) {
+       for my $z ($b->[2] .. $b->[5]) {
+               $seen{$x,$y,$z} = 1;
+       } } }
+}
+
+sub clr_brick {
+       my ($b) = @_;
+
+       for my $x ($b->[0] .. $b->[3]) {
+       for my $y ($b->[1] .. $b->[4]) {
+       for my $z ($b->[2] .. $b->[5]) {
+               undef $seen{$x,$y,$z};
+       } } }
+}
+
+sub can_fall {
+       my ($b) = @_;
+
+       return undef if !$b->[5];
+       my $z = $b->[5]-1;
+
+       for my $x ($b->[0] .. $b->[3]) {
+       for my $y ($b->[1] .. $b->[4]) {
+               return undef if $seen{$x,$y,$b->[2]-1};
+       } }
+       return 1;
+}
+
+set_brick($_) for @bricks;
+
+while (1) {
+       my $fallen;
+       my $i = 0;
+       for my $b (@bricks) {
+               $i++;
+               next if !can_fall($b);
+               # say "falling $i (@$b)";
+               clr_brick($b);
+               $b->[2]--; $b->[5]--;
+               set_brick($b);
+               # say "fallen  $i (@$b)";
+               $fallen++;
+       }
+       last if !$fallen;
+}
+
+my $count = 0;
+my (%supported, %supports);
+for my $bi0 (0 .. $#bricks) {
+       my $b0 = $bricks[$bi0];
+       my $cnt = 0;
+       BRICK:
+       for my $bi1 (0 .. $#bricks) {
+               next if $bi0 == $bi1;
+               my $b1 = $bricks[$bi1];
+               # say "possibly supports $bi0 (@$b0) $bi1 (@$b1)";
+               next if $b1->[2] != $b0->[5]+1;
+               for my $x0 ($b0->[0] .. $b0->[3]) {
+               for my $x1 ($b1->[0] .. $b1->[3]) {
+                       next if $x0 != $x1;
+                       for my $y0 ($b0->[1] .. $b0->[4]) {
+                       for my $y1 ($b1->[1] .. $b1->[4]) {
+                               next if $y0 != $y1;
+                               $supports{$bi0}->{$bi1}++;
+                               $supported{$bi1}->{$bi0}++;
+                               next BRICK;
+                       } }
+               } }
+       }
+}
+SBRICK:
+for my $bi0 (0 .. $#bricks) {
+       for my $bi1 (keys %{ $supports{$bi0} }) {
+               next SBRICK if keys(%{ $supported{$bi1} }) == 1;
+       }
+       $count++;
+}
+
+say $count;
diff --git a/2023/44.pl b/2023/44.pl
new file mode 100755 (executable)
index 0000000..e8ee0c7
--- /dev/null
@@ -0,0 +1,88 @@
+#!/usr/bin/perl -w
+
+use v5.38;
+use experimental 'multidimensional';
+$; = ';';
+
+my @bricks = map { [ /\d+/g ] } <>;
+my %seen;
+sub set_brick {
+       my ($b) = @_;
+
+       for my $x ($b->[0] .. $b->[3]) {
+       for my $y ($b->[1] .. $b->[4]) {
+       for my $z ($b->[2] .. $b->[5]) {
+               $seen{$x,$y,$z} = 1;
+       } } }
+}
+
+sub clr_brick {
+       my ($b) = @_;
+
+       for my $x ($b->[0] .. $b->[3]) {
+       for my $y ($b->[1] .. $b->[4]) {
+       for my $z ($b->[2] .. $b->[5]) {
+               undef $seen{$x,$y,$z};
+       } } }
+}
+
+sub can_fall {
+       my ($b) = @_;
+
+       return undef if !$b->[2];
+       my $z = $b->[2]-1;
+
+       for my $x ($b->[0] .. $b->[3]) {
+       for my $y ($b->[1] .. $b->[4]) {
+               return undef if $seen{$x,$y,$z};
+       } }
+       return 1;
+}
+
+set_brick($_) for @bricks;
+
+while (1) {
+       my $fallen;
+       my $i = 0;
+       for my $b (@bricks) {
+               $i++;
+               next if !can_fall($b);
+               # say "falling $i (@$b)";
+               clr_brick($b);
+               $b->[2]--; $b->[5]--;
+               set_brick($b);
+               # say "fallen  $i (@$b)";
+               $fallen++;
+       }
+       last if !$fallen;
+}
+
+my $sum;
+SBRICK:
+for my $bi0 (0 .. $#bricks) {
+       my @bricks1 = map { [ @$_ ] } @bricks;
+       splice @bricks1, $bi0, 1;
+       %seen = ();
+       set_brick($_) for @bricks1;
+       my %f;
+       while (1) {
+               my $fallen;
+               my $i = 0;
+               for my $bi1 (0 .. $#bricks1) {
+                       my $b1 = $bricks1[$bi1];
+                       next if !can_fall($b1);
+                       # say "falling $i (@$b1)";
+                       clr_brick($b1);
+                       $b1->[2]--; $b1->[5]--;
+                       set_brick($b1);
+                       # say "fallen  $bi1 (@$b1)";
+                       $fallen++;
+                       $f{$bi1}++;
+               }
+               last if !$fallen;
+       }
+       # say "falling $bi0 (@{ $bricks[$bi0] }) falls ", join(',',sort keys %f);
+       $sum += keys %f;
+}
+
+say $sum;