diff options
| -rw-r--r-- | challenge-229/polettix/blog.txt | 1 | ||||
| -rw-r--r-- | challenge-229/polettix/blog1.txt | 1 | ||||
| -rw-r--r-- | challenge-229/polettix/perl/ch-1.pl | 32 | ||||
| -rw-r--r-- | challenge-229/polettix/perl/ch-2.pl | 58 | ||||
| -rw-r--r-- | challenge-229/polettix/raku/ch-1.raku | 27 | ||||
| -rw-r--r-- | challenge-229/polettix/raku/ch-2.raku | 50 |
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; +} |
