]> www.fi.muni.cz Git - aoc.git/blobdiff - 2023/28.pl
Day 14 part 2: pure regex-based solution
[aoc.git] / 2023 / 28.pl
index 7135ca558336ee5b39994d2d2cff5c5ab335fadf..2d147f4829c4d98ef73fae13860894cf93a4745d 100755 (executable)
@@ -2,91 +2,24 @@
 
 use v5.38;
 
-my @map = map { chomp; [ split // ] } <>;
-my $xmax = $#{ $map[0] };
-my $ymax = $#map;
+my $map; { local $/; $map = <>; }
 
-my %seen;
-my @rounds;
-my $round;
-while (1) {
-       $round++;
-       my $retry;
-       $retry = 1;
-       while ($retry) {
-               $retry = 0;
-               for my $y (1 .. $ymax) {
-                       for my $x (0 .. $xmax) {
-                               if ($map[$y][$x] eq 'O' && $map[$y-1][$x] eq '.') {
-                                       $map[$y-1][$x] = 'O';
-                                       $map[$y][$x] = '.';
-                                       $retry = 1;
-                               }
-                       }
-               }
+my (@score, %seen, $round);
+while (++$round) {
+       for (1 .. 4) {
+               my $map1;
+               do { # rotate the map:
+                       $map1 .= join('', reverse $map =~ /^./gm) . "\n"
+               } while $map =~ s/^.//gm;
+               chomp ($map = $map1);
+               1 while $map =~ s/O(\.+)/$1O/g; # move O's to the right
        }
-       $retry = 1;
-       while ($retry) {
-               $retry = 0;
-               for my $x (1 .. $xmax) {
-                       for my $y (0 .. $ymax) {
-                               if ($map[$y][$x] eq 'O' && $map[$y][$x-1] eq '.') {
-                                       $map[$y][$x-1] = 'O';
-                                       $map[$y][$x] = '.';
-                                       $retry = 1;
-                               }
-                       }
-               }
-       }
-       $retry = 1;
-       while ($retry) {
-               $retry = 0;
-               for my $y (reverse 0 .. $ymax-1) {
-                       for my $x (0 .. $xmax) {
-                               if ($map[$y][$x] eq 'O' && $map[$y+1][$x] eq '.') {
-                                       $map[$y+1][$x] = 'O';
-                                       $map[$y][$x] = '.';
-                                       $retry = 1;
-                               }
-                       }
-               }
-       }
-       $retry = 1;
-       while ($retry) {
-               $retry = 0;
-               for my $x (reverse 0 .. $xmax-1) {
-                       for my $y (0 .. $ymax) {
-                               if ($map[$y][$x] eq 'O' && $map[$y][$x+1] eq '.') {
-                                       $map[$y][$x+1] = 'O';
-                                       $map[$y][$x] = '.';
-                                       $retry = 1;
-                               }
-                       }
-               }
-       }
-               
-       # say join('', @$_) for @map;
+       $score[$round] +=()= substr($map, pos($map)) =~ /\n/g
+               while $map =~ /O/g;
 
-       my $sum;
-       for my $y (0 .. $ymax) {
-               for my $x (0 .. $xmax) {
-                       $sum += $ymax + 1 - $y if $map[$y][$x] eq 'O';
-               }
-       }
-       say $sum;
-       $rounds[$round] = $sum;
-       say "round $round sum $sum";
-       my $map = join("\n", map { join('', @$_) } @map);
-       if ($seen{$map}) {
-               say "round $round seen also at $seen{$map}";
-               my $period = $round - $seen{$map};
-               my $total = 1000000000;
-               $total -= $round;
-               $total %= $period;
-               say "looking at ", $round - $period + $total;
-               say $rounds[$round-$period+$total];
-               last;
-       }
+       last if $seen{$map};
        $seen{$map} = $round;
 }
 
+my $remains = (1000000000 - $round) % ($round - $seen{$map});
+say $score[$seen{$map} + $remains];