]> www.fi.muni.cz Git - aoc.git/commitdiff
Day 15: corner cases
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Mon, 16 Dec 2024 09:02:05 +0000 (10:02 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Mon, 16 Dec 2024 09:02:05 +0000 (10:02 +0100)
2024/29.pl [new file with mode: 0755]
2024/30.pl [new file with mode: 0755]

diff --git a/2024/29.pl b/2024/29.pl
new file mode 100755 (executable)
index 0000000..ded1153
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/perl -w
+
+use v5.40;
+
+my ($x, $y);
+my @map;
+while (<>) {
+       chomp;
+       last if /^$/;
+       if (/@/g) { $x = pos()-1; $y = $.-1; }
+       push @map, [ split // ];
+}
+
+my $xmax = $#{ $map[0] };
+my $ymax = $#map;
+
+my %dir = (
+       '^' => [  0, -1 ],
+       '<' => [ -1,  0 ],
+       '>' => [  1,  0 ],
+       'v' => [  0,  1 ],
+);
+
+while (<>) {
+       chomp;
+       for my $d (split //) {
+               my ($dx, $dy) = $dir{$d}->@*;
+               my ($x1, $y1) = ($x+$dx, $y+$dy);
+               my ($nx, $ny) = ($x+$dx, $y+$dy);
+               while (1) {
+                       last if $map[$ny][$nx] eq '#';
+                       if ($map[$ny][$nx] eq '.') {
+                               if ($map[$y1][$x1] eq 'O') {
+                                       $map[$ny][$nx] = 'O';
+                               }
+                               $map[$y][$x] = '.';
+                               $map[$y1][$x1] = '@';
+                               $x = $x1;
+                               $y = $y1;
+                               last;
+                       }
+                       $nx += $dx;
+                       $ny += $dy;
+               }
+       }
+}
+
+my $sum;
+for my $y (0 .. $ymax) {
+       for my $x (0 .. $xmax) {
+               if ($map[$y][$x] eq 'O') {
+                       $sum += 100*$y+$x;
+               }
+               print $map[$y][$x];
+       }
+       print "\n";
+}
+
+say $sum;
+
diff --git a/2024/30.pl b/2024/30.pl
new file mode 100755 (executable)
index 0000000..39fd677
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/perl -w
+
+use v5.40;
+
+my ($x, $y);
+my @map;
+while (<>) {
+       chomp;
+       last if /^$/;
+       s/#/##/g;
+       s/\./../g;
+       s/O/[]/g;
+       s/@/@./g;
+       if (/@/g) { $x = pos()-1; $y = $.-1; }
+       push @map, [ split // ];
+}
+
+my $xmax = $#{ $map[0] };
+my $ymax = $#map;
+
+say "start at $x,$y";
+
+my %dir = (
+       '^' => [  0, -1 ],
+       '<' => [ -1,  0 ],
+       '>' => [  1,  0 ],
+       'v' => [  0,  1 ],
+);
+
+sub can_move {
+       my ($x, $y, $dx, $dy) = @_;
+
+       my $nx = $x+$dx;
+       my $ny = $y+$dy;
+       my $m = $map[$ny][$nx];
+
+       return () if $m eq '#';
+       return [$x,$y] if $m eq '.';
+
+       my (@r1, @r2);
+       if ($dy) {
+               if ($m eq '[') {
+                       @r1 = can_move($nx, $ny, $dx, $dy);
+                       @r2 = can_move($nx+1, $ny, $dx, $dy);
+               } elsif ($map[$ny][$nx] eq ']') {
+                       @r1 = can_move($nx, $ny, $dx, $dy);
+                       @r2 = can_move($nx-1, $ny, $dx, $dy);
+               }
+               if (@r1 && @r2) {
+                       return ([$x, $y], @r1, @r2);
+               } else {
+                       return ();
+               }
+       } else {
+               if ($dx == 1) {
+                       my @rv = can_move($nx+1, $ny, $dx, $dy);
+                       if (@rv) {
+                               return ([$x, $y], [$x+1, $y], @rv);
+                       } else {
+                               return ();
+                       }
+               } else {
+                       my @rv = can_move($nx-1, $ny, $dx, $dy);
+                       if (@rv) {
+                               return ([$x,$y], [$x-1, $y], @rv);
+                       } else {
+                               return ();
+                       }
+               }
+       }
+}
+
+while (<>) {
+       chomp;
+       for my $d (split //) {
+               my ($dx, $dy) = $dir{$d}->@*;
+               my @rv = can_move($x, $y, $dx, $dy);
+               my %seen;
+               for my $obj (reverse @rv) {
+                       my ($x, $y) = @$obj;
+                       next if $seen{"$x,$y"}++;
+                       my $nx = $x+$dx;
+                       my $ny = $y+$dy;
+                       # say "moving $x,$y to $nx,$ny $map[$y][$x]";
+                       $map[$ny][$nx] = $map[$y][$x];
+                       $map[$y][$x] = '.';
+               }
+               if (@rv) {
+                       $x += $dx; $y += $dy;
+               }
+       }
+}
+
+my $sum;
+for my $y (0 .. $ymax) {
+       for my $x (0 .. $xmax) {
+               if ($map[$y][$x] eq '[') {
+                       $sum += 100*$y+$x;
+               }
+               print $map[$y][$x];
+       }
+       print "\n";
+}
+
+say $sum;
+