my $ymax = $#map;
my $sum;
-my $retry = 1;
-while ($retry) {
- $retry = 0;
-for my $y (1 .. $ymax) {
+for my $y (0 .. $ymax) {
for my $x (0 .. $xmax) {
- if ($map[$y][$x] eq 'O' && $map[$y-1][$x] eq '.') {
- $map[$y-1][$x] = 'O';
+ next if $map[$y][$x] ne 'O';
+ my $y1 = $y;
+ $y1-- while $y1 && $map[$y1-1][$x] eq '.';
+ if ($y1 != $y) {
+ $map[$y1][$x] = 'O';
$map[$y][$x] = '.';
- $retry = 1;
}
+ $sum += $ymax + 1 - $y1;
}
}
-}
-
-say join('', @$_) for @map;
-for my $y (0 .. $ymax) {
- for my $x (0 .. $xmax) {
- $sum += $ymax + 1 - $y if $map[$y][$x] eq 'O';
- }
-}
+say join('', @$_) for @map;
say $sum;
my $ymax = $#map;
my %seen;
-my @rounds;
+my @score;
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;
- }
- }
- }
- }
- $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) {
+my $key;
+
+while (++$round) {
+ for (1 .. 4) {
+ for my $y (0 .. $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;
- }
- }
- }
- }
- $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;
+ 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);
}
-
- # say join('', @$_) for @map;
- my $sum;
+ $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';
}
}
- 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;
- }
- $seen{$map} = $round;
+
+ $seen{$key} = $round;
+ $score[$round] = $sum;
}
+my $remains = (1000000000 - $round) % ($round - $seen{$key});
+say $score[$seen{$key} + $remains];