aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-229/polettix/blog.txt1
-rw-r--r--challenge-229/polettix/blog1.txt1
-rw-r--r--challenge-229/polettix/perl/ch-1.pl32
-rw-r--r--challenge-229/polettix/perl/ch-2.pl58
-rw-r--r--challenge-229/polettix/raku/ch-1.raku27
-rw-r--r--challenge-229/polettix/raku/ch-2.raku50
6 files changed, 169 insertions, 0 deletions
diff --git a/challenge-229/polettix/blog.txt b/challenge-229/polettix/blog.txt
new file mode 100644
index 0000000000..2f05528b82
--- /dev/null
+++ b/challenge-229/polettix/blog.txt
@@ -0,0 +1 @@
+https://etoobusy.polettix.it/2023/09/29/pwc236-exact-change/
diff --git a/challenge-229/polettix/blog1.txt b/challenge-229/polettix/blog1.txt
new file mode 100644
index 0000000000..e7b1ef6414
--- /dev/null
+++ b/challenge-229/polettix/blog1.txt
@@ -0,0 +1 @@
+https://etoobusy.polettix.it/2023/10/01/pwc236-array-loops/
diff --git a/challenge-229/polettix/perl/ch-1.pl b/challenge-229/polettix/perl/ch-1.pl
new file mode 100644
index 0000000000..328151d212
--- /dev/null
+++ b/challenge-229/polettix/perl/ch-1.pl
@@ -0,0 +1,32 @@
+#!/usr/bin/env perl
+use v5.24;
+use warnings;
+use experimental 'signatures';
+
+say exact_change(@ARGV) ? 'true' : 'false';
+
+sub exact_change (@bills) {
+ my %bills_of = map { $_ => 0 } (5, 10, 20);
+ for my $bill (@bills) {
+ if ($bill == 5) {
+ $bills_of{5}++;
+ }
+ elsif ($bill == 10) {
+ return 0 unless $bills_of{5}-- > 0;
+ $bills_of{10}++;
+ }
+ else { # $bill == 20
+ return 0 unless $bills_of{5}-- > 0;
+ if ($bills_of{10} >= 1) {
+ $bills_of{10}--;
+ }
+ elsif ($bills_of{5} >= 2) {
+ $bills_of{5} -= 2;
+ }
+ else {
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
diff --git a/challenge-229/polettix/perl/ch-2.pl b/challenge-229/polettix/perl/ch-2.pl
new file mode 100644
index 0000000000..d70d42d0d6
--- /dev/null
+++ b/challenge-229/polettix/perl/ch-2.pl
@@ -0,0 +1,58 @@
+#!/usr/bin/env perl
+use v5.24;
+use warnings;
+use experimental 'signatures';
+
+say array_loops(map { split m{\D+}mxs } @ARGV);
+
+sub array_loops (@ints) {
+ my $uf = UnionFind->new(components => [0 .. $#ints]);
+ $uf->union($_, $ints[$_]) for 0 .. $#ints;
+ return $uf->count;
+}
+
+
+package UnionFind; # Sedgewick & Wayne, Algorithms 4th ed, ยง1.5
+use strict;
+
+sub add; # see below
+sub connected { return $_[0]->find($_[1]) eq $_[0]->find($_[2]) }
+sub count { return $_[0]{count} }
+sub find { return $_[0]{cs}{$_[0]->find_id($_[1])}[1] }
+sub find_id; # see below
+sub new; # see below
+sub union; # see below
+
+sub add {
+ my $id = $_[0]{id_of}->($_[1]);
+ return $_[0] if $_[0]{cs}{$id};
+ $_[0]{cs}{$id} = [$id, $_[1], 1];
+ $_[0]{count}++;
+ return $_[0];
+}
+
+sub find_id {
+ my $r = my $i = $_[0]{id_of}->($_[1]);
+ return unless exists $_[0]{cs}{$r};
+ $r = $_[0]{cs}{$r}[0] while $r ne $_[0]{cs}{$r}[0];
+ ($i, $_[0]{cs}{$i}) = ($_[0]{cs}{$i}[0], $_[0]{cs}{$r}) while $i ne $r;
+ return $r;
+} ## end sub find_id
+
+sub new {
+ my ($pk, %args) = (@_ > 0 && ref($_[1])) ? ($_[0], %{$_[1]}) : @_;
+ my $id_of = $args{identifier} || sub { return "$_[0]" };
+ my $self = bless {id_of => $id_of, count => 0}, $pk;
+ $self->add($_) for @{$args{components} || []};
+ return $self;
+} ## end sub new
+
+sub union {
+ my ($i, $j) = ($_[0]->find_id($_[1]), $_[0]->find_id($_[2]));
+ return $_[0] if $i eq $j;
+ ($i, $j) = ($j, $i) if $_[0]{cs}{$i}[2] < $_[0]{cs}{$j}[2]; # i -> max
+ $_[0]{cs}{$i}[2] += $_[0]{cs}{$j}[2];
+ $_[0]{cs}{$j} = $_[0]{cs}{$i};
+ $_[0]{count}--;
+ return $_[0];
+} ## end sub union
diff --git a/challenge-229/polettix/raku/ch-1.raku b/challenge-229/polettix/raku/ch-1.raku
new file mode 100644
index 0000000000..17215514d4
--- /dev/null
+++ b/challenge-229/polettix/raku/ch-1.raku
@@ -0,0 +1,27 @@
+#!/usr/bin/env raku
+use v6;
+sub MAIN (*@bills) { put exact-change(@bills) ?? 'true' !! 'false' }
+
+sub exact-change (@bills) {
+ my %bills-of = <5 0 10 0 20 0>;
+ for @bills -> $bill {
+ if $bill == 5 { %bills-of<5>++ }
+ elsif $bill == 10 {
+ return False unless %bills-of<5>-- > 0;
+ %bills-of<10>++;
+ }
+ else { # $bill == 20
+ return False unless %bills-of<5>-- > 0;
+ if %bills-of<10> >= 1 {
+ %bills-of<10>--;
+ }
+ elsif %bills-of<5> >= 2 {
+ %bills-of<5> -= 2;
+ }
+ else {
+ return False;
+ }
+ }
+ }
+ return True;
+}
diff --git a/challenge-229/polettix/raku/ch-2.raku b/challenge-229/polettix/raku/ch-2.raku
new file mode 100644
index 0000000000..8ce5f3ad90
--- /dev/null
+++ b/challenge-229/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;
+}