]> www.fi.muni.cz Git - aoc.git/commitdiff
Day 17: quite tedious
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Sat, 17 Dec 2022 07:23:03 +0000 (08:23 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Sat, 17 Dec 2022 07:23:03 +0000 (08:23 +0100)
2022/33.pl [new file with mode: 0755]
2022/34.pl [new file with mode: 0755]

diff --git a/2022/33.pl b/2022/33.pl
new file mode 100755 (executable)
index 0000000..8cc0b2d
--- /dev/null
@@ -0,0 +1,70 @@
+#!/usr/bin/perl -w
+
+use v5.36;
+use strict;
+
+$_ = <>;
+my @moves = /(\S)/g;
+
+my @units = (
+       [ [0, 0], [1, 0], [2, 0], [3, 0] ], # horiz i
+       [ [0, 1], [1, 1], [2, 1], [1, 0], [1, 2] ], # x
+       [ [0, 0], [1, 0], [2, 0], [2, 1], [2, 2] ], # v
+       [ [0, 0], [0, 1], [0, 2], [0, 3] ], # vert i
+       [ [0, 0], [0, 1], [1, 0], [1, 1] ], # o
+);
+
+my @map;
+my $w = 7;
+my $h = 0;
+
+my $units = 0;
+my $move = 0;
+
+sub can_move($unit, $vect) {
+       # say "can_move $vect->[0] $vect->[1]";
+       for my $pt (@$unit) {
+               my @dst = ($pt->[0] + $vect->[0], $pt->[1] + $vect->[1]);
+               return 0 if $dst[0] < 0 || $dst[0] >= $w;
+               return 0 if $dst[1] < 0;
+               return 0 if $map[$dst[1]][$dst[0]];
+       }
+       return 1;
+}
+
+sub dump_map {
+       for my $y (reverse 0 .. $h) {
+               for my $x (0 .. $w-1) {
+                       print $map[$y][$x] ? '#' : ' ';
+               }
+               print "\n";
+       }
+       say "---- $h ----";
+}
+
+while ($units < 2022) {
+       my $u = $units[$units % @units];
+       my ($x, $y) = (2, $h+3);
+       while (1) {     
+               my $m = $moves[$move++];
+               $move = 0 if $move > $#moves;
+               if ($m eq '>') {
+                       $x++ if can_move($u, [$x+1, $y]);
+               } else {
+                       $x-- if can_move($u, [$x-1, $y]);
+               }
+               if (can_move($u, [$x, $y-1])) {
+                       $y--;
+                       next;
+               }
+               last;
+       }
+       for my $pt (@$u) {
+               $map[$y + $pt->[1]][$x + $pt->[0]] = 1;
+               $h = 1 + $y + $pt->[1] if $h < 1 + $y + $pt->[1];
+       }
+       # dump_map();
+       $units++;
+}
+
+say $h;
diff --git a/2022/34.pl b/2022/34.pl
new file mode 100755 (executable)
index 0000000..01ed70a
--- /dev/null
@@ -0,0 +1,98 @@
+#!/usr/bin/perl -w
+
+use v5.36;
+use strict;
+
+$_ = <>;
+my @moves = /(\S)/g;
+
+my @units = (
+       [ [0, 0], [1, 0], [2, 0], [3, 0] ], # horiz i
+       [ [0, 1], [1, 1], [2, 1], [1, 0], [1, 2] ], # x
+       [ [0, 0], [1, 0], [2, 0], [2, 1], [2, 2] ], # v
+       [ [0, 0], [0, 1], [0, 2], [0, 3] ], # vert i
+       [ [0, 0], [0, 1], [1, 0], [1, 1] ], # o
+);
+
+my $w = 7;
+my $h = 0;
+my @map;
+my $map_top = 0;
+my $max_map = 100;
+
+my $units = 0;
+my $move = 0;
+
+sub can_move($unit, $vect) {
+       # say "can_move $vect->[0] $vect->[1]";
+       for my $pt (@$unit) {
+               my @dst = ($pt->[0] + $vect->[0], $pt->[1] + $vect->[1]);
+               return 0 if $dst[0] < 0 || $dst[0] >= $w;
+               return 0 if $dst[1] < 0;
+               return 0 if $map[$dst[1]-$map_top][$dst[0]];
+       }
+       return 1;
+}
+
+sub move_unit {
+       my $u = $units[$units % @units];
+       # say "unit $units h=$h";
+       # say "$state";
+       my ($x, $y) = (2, $h+3);
+       while (1) {     
+               my $m = $moves[$move++];
+               # say "$x $y $m";
+               $move = 0 if $move > $#moves;
+               if ($m eq '>') {
+                       $x++ if can_move($u, [$x+1, $y]);
+               } else {
+                       $x-- if can_move($u, [$x-1, $y]);
+               }
+               if (can_move($u, [$x, $y-1])) {
+                       $y--;
+                       next;
+               }
+               last;
+       }
+       for my $pt (@$u) {
+               $map[$y + $pt->[1] - $map_top][$x + $pt->[0]] = 1;
+               $h = 1 + $y + $pt->[1] if $h < 1 + $y + $pt->[1];
+               while (@map > $max_map) {
+                       shift @map;
+                       $map_top++;
+               }
+       }
+       $units++;
+}
+
+my %seen;
+
+while (1) {
+       my $state = join(' ', $units % @units, $move);
+       for my $y (0 .. $#map) {
+               my $n = 0;
+               for my $x (0 .. $w-1) {
+                       $n <<= 1;
+                       $n |= 1 if $map[$y][$x];
+               }
+               $state .= sprintf(" %02x", $n);
+       }
+       if ($seen{$state}) {
+               my ($first_u, $first_h) = $seen{$state} =~ /(\d+) (\d+)$/;
+               my $u_diff = $units - $first_u;
+               my $h_diff = $h - $first_h;
+               # say "$state $units $h\n$seen{$state}\n\n";
+               my $n = int((1000000000000-$units)/$u_diff);
+               $h += $n * $h_diff;
+               $map_top += $n * $h_diff;
+               $units += $n * $u_diff;
+               while ($units < 1000000000000) {
+                       move_unit;
+               }
+               last;
+       }
+       $seen{$state} = $state . " $units $h";
+       move_unit;
+}
+
+say $h;