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];