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