use v5.38;
-my @map = map { chomp; [ split // ] } <>;
-my $xmax = $#{ $map[0] };
-my $ymax = $#map;
-
-my %seen;
-my @score;
-my $round;
-my $key;
+my $map; { local $/; $map = <>; }
+my (@score, %seen, $round);
while (++$round) {
for (1 .. 4) {
- for my $y (0 .. $ymax) {
- for my $x (0 .. $xmax) {
- next if $map[$y][$x] ne 'O';
- my $y1 = $y;
- while ($y1 && $map[$y1-1][$x] eq '.') {
- $map[$y1][$x] = '.';
- $map[--$y1][$x] = 'O';
- }
- }
- }
-
- @map = map { # rotate clockwise
- my $x = $_;
- [ map { $map[$_][$x] } reverse 0 .. $ymax ]
- } 0 .. $xmax;
- ($xmax, $ymax) = ($ymax, $xmax);
- }
-
- $key = join("\n", map { join('', @$_) } @map);
- last if $seen{$key};
-
- my $sum = 0;
- for my $y (0 .. $ymax) {
- for my $x (0 .. $xmax) {
- $sum += $ymax + 1 - $y if $map[$y][$x] eq 'O';
- }
+ 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
}
+ $score[$round] +=()= substr($map, pos($map)) =~ /\n/g
+ while $map =~ /O/g;
- $seen{$key} = $round;
- $score[$round] = $sum;
+ last if $seen{$map};
+ $seen{$map} = $round;
}
-my $remains = (1000000000 - $round) % ($round - $seen{$key});
-say $score[$seen{$key} + $remains];
+my $remains = (1000000000 - $round) % ($round - $seen{$map});
+say $score[$seen{$map} + $remains];