]> www.fi.muni.cz Git - aoc2021.git/commitdiff
Day 9 task 2: one-pass solution
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Thu, 9 Dec 2021 07:56:34 +0000 (08:56 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Thu, 9 Dec 2021 07:56:34 +0000 (08:56 +0100)
18.pl

diff --git a/18.pl b/18.pl
index c4223b45877d9bc4cca9da6c9071168ec3c1e6be..f328873cddb94c0736de3a80dfaea9db5a0905b2 100755 (executable)
--- a/18.pl
+++ b/18.pl
@@ -5,52 +5,45 @@ use v5.16;
 my @m = map { chomp; [ split // ]; } <>; 
 my $maxy = $#m;
 my $maxx = $#{$m[0]};
-say "$maxx x $maxy";
-
-my @low;
-for my $y (0 .. $maxy) {
-       for my $x (0 .. $maxx) {
-               my $val = $m[$y][$x];
-               next if $y > 0     && $m[$y-1][$x] <= $val;
-               next if $y < $maxy && $m[$y+1][$x] <= $val;
-               next if $x > 0     && $m[$y][$x-1] <= $val;
-               next if $x < $maxx && $m[$y][$x+1] <= $val;
-               push @low, [$x, $y];
-       }
-}
 
-my @sizes;
-
-for my $start (@low) {
-       my $added = 0;
-       my $size =1;
-       my @points = ($start);
-       my %pts = (join(',', @$start) => 1);
-       do {
-               $added = 0;
-               for my $p (@points) {
-                       for my $add (([0, 1], [1, 0], [-1, 0], [0, -1])) {
-                               my ($x, $y) = ($p->[0]+$add->[0], $p->[1]+$add->[1]);
-                               # say "trying $x, $y";
-                               next if $pts{join(',',$x,$y)};
-                               next if $x < 0 || $x > $maxx;
-                               next if $y < 0 || $y > $maxy;
-                               next if $m[$y][$x] == 9;
-                               $added = 1;
-                               $pts{join(',',$x,$y)} = 1;
-                               push @points, [$x, $y];
-                               # say "adding $x, $y = $m[$y][$x]";
-                               $size++;
+my @basins;
+my $max_id = 0;
+my @prev_row;
+for my $row (@m) {
+       my $prev_l = undef;
+       for my $i (0 .. $#$row) {
+               my $b_id;
+               if ($row->[$i] == 9) {
+                       $b_id = undef;
+               } elsif (!$prev_l && !$prev_row[$i]) {
+                       $b_id = ++$max_id;
+               } elsif (!$prev_l) {
+                       $b_id = $prev_row[$i];
+               } elsif (!$prev_row[$i] || $prev_l == $prev_row[$i]) {
+                       $b_id = $prev_l;
+               } else { # merge
+                       $b_id = $prev_row[$i];
+                       $basins[$b_id] += $basins[$prev_l];
+                       $basins[$prev_l] = undef;
+                       for my $j (0 .. $#$row) {
+                               next if !$row->[$j] || $row->[$j] != $prev_l;
+                               $row->[$j] = $b_id;
+                       }
+                       for my $j (0 .. $#$row) {
+                               next if !$prev_row[$j] || $prev_row[$j] != $prev_l;
+                               $prev_row[$j] = $b_id;
                        }
                }
-       } while ($added);
-       # say "$start->[0], $start->[1] : $size";
-       push @sizes, $size;
+               $prev_l = $b_id;
+               $row->[$i] = $b_id;
+               $basins[$b_id]++ if defined $b_id;
+       }
+       @prev_row = @$row;
 }
 
-@sizes = sort { $b <=> $a } @sizes;
+@basins = sort { $b <=> $a } grep { defined $_ } @basins;
 
-say $sizes[0]*$sizes[1]*$sizes[2];
+say $basins[0]*$basins[1]*$basins[2];