+#!/usr/bin/perl
+
+use v5.30;
+use strict;
+
+my $in = 'stpzcrnm';
+# my $in = 'flqrgnkx';
+
+sub knot {
+ my $line = shift;
+ my @l = map { ord } split //, $line;
+ push @l, 17, 31, 73, 47, 23;
+
+ my $pos = 0;
+ my $skip = 0;
+ # my @nodes = (0 .. 4);
+ my @nodes = (0 .. 255);
+ my $n = @nodes;
+
+ for (1 .. 64) {
+ for my $i (@l) {
+ my $end = $pos + $i;
+ my @to_rev;
+ # say "pos=$pos skip $skip i=$i ", join(',', @nodes);
+ if ($end > $n) {
+ push @to_rev, splice @nodes, $pos;
+ push @to_rev, splice @nodes, 0, $end - $n;
+ @to_rev = reverse @to_rev;
+ # say "to_rev = ", join(',', @to_rev);
+ unshift @nodes, splice @to_rev, @to_rev-($end-$n);
+ push @nodes, @to_rev;
+ } else {
+ push @to_rev, splice @nodes, $pos, $i;
+ splice @nodes, $pos, 0, reverse @to_rev;
+ }
+ $pos += $i + $skip++;
+ $pos -= $n while $pos >= $n;
+ }
+ }
+
+ my $hash = '';
+ while (my @s = splice (@nodes, 0, 16)) {
+ my $x = 0;
+ $x ^= $_ for @s;
+ $hash .= sprintf("%08b", $x);
+ }
+ return $hash;
+}
+
+my @prev = (0) x 128;
+my %regions;
+my $nr = 1;
+for my $row (0 .. 127) {
+ my $h = knot("$in-$row");
+ my @line = split //, $h;
+ my @nl = (0) x 128;
+ for my $x (0 .. 127) {
+ next if $line[$x] == '0';
+
+ if ($prev[$x]) {
+ $nl[$x] = $prev[$x];
+ } elsif ($x && $nl[$x-1]) {
+ $nl[$x] = $nl[$x-1];
+ } else {
+ $nl[$x] = $nr;
+ $regions{$nr} = 1;
+ $nr++;
+ }
+ if ($x && $nl[$x-1] && $nl[$x-1] != $nl[$x]) {
+ my $old = $nl[$x-1];
+ delete $regions{$old};
+ for (0 .. 127) {
+ $nl[$_] = $nl[$x] if $nl[$_] == $old;
+ $prev[$_] = $nl[$x] if $prev[$_] == $old;
+ }
+ }
+ }
+ @prev = @nl;
+}
+
+say scalar keys %regions;
+