aboutsummaryrefslogtreecommitdiff
path: root/challenge-236/polettix/raku/ch-2.raku
diff options
context:
space:
mode:
Diffstat (limited to 'challenge-236/polettix/raku/ch-2.raku')
-rw-r--r--challenge-236/polettix/raku/ch-2.raku50
1 files changed, 50 insertions, 0 deletions
diff --git a/challenge-236/polettix/raku/ch-2.raku b/challenge-236/polettix/raku/ch-2.raku
new file mode 100644
index 0000000000..8ce5f3ad90
--- /dev/null
+++ b/challenge-236/polettix/raku/ch-2.raku
@@ -0,0 +1,50 @@
+#!/usr/bin/env raku
+use v6;
+
+class UnionFind {
+ has $.count = 0;
+ has %!cs;
+ has &!id-of is built;
+ has @!items;
+
+ method add ($item) {
+ my $id = &!id-of($item);
+ return self if %!cs{$id};
+ %!cs{$id} = [ $id, $item, 1 ];
+ $!count++;
+ return self;
+ }
+
+ method find ($item) { %!cs{self.find-id($item)}[1] }
+
+ method find-id ($item) {
+ my $r = my $i = &!id-of($item);
+ return unless %!cs{$r}:exists;
+ $r = %!cs{$r}[0] while $r ne %!cs{$r}[0];
+ ($i, %!cs{$i}) = (%!cs{$i}[0], %!cs{$r}) while $i ne $r;
+ return $r;
+ }
+
+ method new (:&id-of = -> $n { $n.Str }, :@components) {
+ my $obj = self.bless(:&id-of);
+ $obj.add($_) for @components;
+ return $obj;
+ }
+
+ method union ($p, $q) {
+ my ($i, $j) = self.find-id($p), self.find-id($q);
+ return self if $i eq $j;
+ ($i, $j) = $j, $i if %!cs{$i}[2] < %!cs{$j}[2]; # i -> max
+ %!cs{$i}[2] += %!cs{$j}[2];
+ %!cs{$j} = %!cs{$i};
+ $!count--;
+ return self;
+ }
+}
+
+sub MAIN (*@indexes) {
+ @indexes = @indexes.map({.split(/\D+/)}).flat;
+ my $uf = UnionFind.new(components => [ ^@indexes ]);
+ for @indexes.kv -> $i, $j { $uf.union($i, $j) }
+ put $uf.count;
+}