aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Bell_West <roger@firedrake.org>2023-09-26 15:05:47 +0100
committerRoger Bell_West <roger@firedrake.org>2023-09-26 15:05:47 +0100
commit505f0065a1e22c26aa7347f82f0c899eeda4c396 (patch)
treed14773d2873ba068fc6b15e05229368a2c42ef41
parentdebce30c9732613662c4b075bc70edee05255876 (diff)
downloadperlweeklychallenge-club-505f0065a1e22c26aa7347f82f0c899eeda4c396.tar.gz
perlweeklychallenge-club-505f0065a1e22c26aa7347f82f0c899eeda4c396.tar.bz2
perlweeklychallenge-club-505f0065a1e22c26aa7347f82f0c899eeda4c396.zip
RogerBW solutions for challenge no. 236
-rwxr-xr-xchallenge-236/roger-bell-west/javascript/ch-1.js72
-rwxr-xr-xchallenge-236/roger-bell-west/javascript/ch-2.js54
-rw-r--r--challenge-236/roger-bell-west/kotlin/ch-1.kt72
-rw-r--r--challenge-236/roger-bell-west/kotlin/ch-2.kt54
-rwxr-xr-xchallenge-236/roger-bell-west/lua/ch-1.lua87
-rwxr-xr-xchallenge-236/roger-bell-west/lua/ch-2.lua55
-rwxr-xr-xchallenge-236/roger-bell-west/perl/ch-1.pl59
-rwxr-xr-xchallenge-236/roger-bell-west/perl/ch-2.pl43
-rw-r--r--challenge-236/roger-bell-west/postscript/ch-1.ps221
-rw-r--r--challenge-236/roger-bell-west/postscript/ch-2.ps87
-rwxr-xr-xchallenge-236/roger-bell-west/python/ch-1.py49
-rwxr-xr-xchallenge-236/roger-bell-west/python/ch-2.py40
-rwxr-xr-xchallenge-236/roger-bell-west/raku/ch-1.p656
-rwxr-xr-xchallenge-236/roger-bell-west/raku/ch-2.p641
-rwxr-xr-xchallenge-236/roger-bell-west/ruby/ch-1.rb62
-rwxr-xr-xchallenge-236/roger-bell-west/ruby/ch-2.rb53
-rwxr-xr-xchallenge-236/roger-bell-west/rust/ch-1.rs71
-rwxr-xr-xchallenge-236/roger-bell-west/rust/ch-2.rs69
-rw-r--r--challenge-236/roger-bell-west/scala/ch-1.scala66
-rw-r--r--challenge-236/roger-bell-west/scala/ch-2.scala58
-rw-r--r--challenge-236/roger-bell-west/tests.yaml92
21 files changed, 1461 insertions, 0 deletions
diff --git a/challenge-236/roger-bell-west/javascript/ch-1.js b/challenge-236/roger-bell-west/javascript/ch-1.js
new file mode 100755
index 0000000000..98b6a4569e
--- /dev/null
+++ b/challenge-236/roger-bell-west/javascript/ch-1.js
@@ -0,0 +1,72 @@
+#! /usr/bin/node
+
+"use strict"
+
+function Reserve(vv) {
+ let r = Object.create(Reserve.methods);
+ let vq = vv.sort(function(a, b) {
+ return b - a;
+ });
+ r.values = vq;
+ r.counts = [];
+ r.vm = new Map;
+ for (let i = 0; i < vq.length; i++) {
+ r.counts.push(0);
+ r.vm.set(vq[i], i);
+ }
+ return r;
+}
+
+Reserve.methods = {
+ makechange(price, tendered) {
+ let val = 0;
+ for (let note of tendered) {
+ if (!this.vm.has(note)) {
+ return false;
+ }
+ this.counts[this.vm.get(note)]++;
+ val += note;
+ }
+ if (val < price) {
+ return false;
+ }
+ val -= price;
+ for (let bid = 0; bid < this.values.length; bid++) {
+ while (val >= this.values[bid] && this.counts[bid] > 0) {
+ val -= this.values[bid];
+ this.counts[bid]--;
+ }
+ }
+ return (val == 0);
+ }
+}
+
+function exactchange(a) {
+ var reserve = Reserve([5, 10, 20])
+ for (let tendered of a) {
+ if (!reserve.makechange(5, [tendered])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+if (exactchange([5, 5, 5, 10, 20])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (!exactchange([5, 5, 10, 10, 20])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (exactchange([5, 5, 5, 20])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-236/roger-bell-west/javascript/ch-2.js b/challenge-236/roger-bell-west/javascript/ch-2.js
new file mode 100755
index 0000000000..2af581a1ea
--- /dev/null
+++ b/challenge-236/roger-bell-west/javascript/ch-2.js
@@ -0,0 +1,54 @@
+#! /usr/bin/node
+
+"use strict"
+
+function arrayloops(a) {
+ let loop_id = 0;
+ let loops = new Map;
+ for (let origin = 0; origin < a.length; origin++) {
+ if (!loops.has(origin)) {
+ let li = 0;
+ let thisloop = new Set;
+ let x = origin;
+ while (true) {
+ if (x >= a.length) {
+ break;
+ }
+ thisloop.add(x);
+ x = a[x];
+ if (loops.has(x)) {
+ li = loops.get(x);
+ break;
+ }
+ if (thisloop.has(x)) {
+ loop_id += 1;
+ li = loop_id;
+ break;
+ }
+ }
+ for (let i of thisloop) {
+ loops.set(i, li);
+ }
+ }
+ }
+ return loop_id;
+}
+
+if (arrayloops([4, 6, 3, 8, 15, 0, 13, 18, 7, 16, 14, 19, 17, 5, 11, 1, 12, 2, 9, 10]) == 3) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (arrayloops([0, 1, 13, 7, 6, 8, 10, 11, 2, 14, 16, 4, 12, 9, 17, 5, 3, 18, 15, 19]) == 6) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (arrayloops([9, 8, 3, 11, 5, 7, 13, 19, 12, 4, 14, 10, 18, 2, 16, 1, 0, 15, 6, 17]) == 1) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-236/roger-bell-west/kotlin/ch-1.kt b/challenge-236/roger-bell-west/kotlin/ch-1.kt
new file mode 100644
index 0000000000..e72f15fedc
--- /dev/null
+++ b/challenge-236/roger-bell-west/kotlin/ch-1.kt
@@ -0,0 +1,72 @@
+class Reserve(vls: List<Int>) {
+ var vll: ArrayList<Int> = ArrayList(0)
+ var counts: ArrayList<Int> = ArrayList(0)
+ var vm = mutableMapOf<Int, Int>()
+
+ init {
+ var vq = ArrayList(vls)
+ vq.sort()
+ vq.reverse()
+ vll = vq
+ for (i in 1..vq.size) {
+ counts.add(0)
+ }
+ vq.forEachIndexed {i, v -> vm.put(v, i)}
+ }
+
+ fun makechange(price: Int, tendered: List<Int>): Boolean {
+ var vl = 0
+ for (note in tendered) {
+ if (!vm.contains(note)) {
+ return false
+ }
+ counts[vm.getValue(note)] += 1
+ vl += note
+ }
+ if (vl < price) {
+ return false
+ }
+ vl -= price
+ for (bid in 0..vll.size-1) {
+ while (vl >= vll[bid] && counts[bid] > 0) {
+ vl -= vll[bid]
+ counts[bid] -= 1
+ }
+ }
+ return (vl == 0)
+ }
+}
+
+fun exactchange(a: List<Int>): Boolean {
+ var reserve = Reserve(listOf(5, 10, 20))
+ for (tendered in a) {
+ if (!reserve.makechange(5, listOf(tendered))) {
+ return false
+ }
+ }
+ return true
+}
+
+
+fun main() {
+
+ if (exactchange(listOf(5, 5, 5, 10, 20))) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (!exactchange(listOf(5, 5, 10, 10, 20))) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (exactchange(listOf(5, 5, 5, 20))) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-236/roger-bell-west/kotlin/ch-2.kt b/challenge-236/roger-bell-west/kotlin/ch-2.kt
new file mode 100644
index 0000000000..dc176509dd
--- /dev/null
+++ b/challenge-236/roger-bell-west/kotlin/ch-2.kt
@@ -0,0 +1,54 @@
+fun arrayloops(a: List<Int>): Int {
+ var loop_id = 0
+ var loops = mutableMapOf<Int, Int>()
+ for (origin in 0..a.size-1) {
+ if (!loops.contains(origin)) {
+ var li = 0
+ var thisloop = mutableSetOf<Int>()
+ var x = origin
+ while (true) {
+ if (x >= a.size) {
+ break
+ }
+ thisloop.add(x)
+ x = a[x]
+ if (loops.contains(x)) {
+ li = loops.getValue(x)
+ break
+ }
+ if (thisloop.contains(x)) {
+ loop_id += 1
+ li = loop_id
+ break
+ }
+ }
+ for (i in thisloop) {
+ loops.put(i, li)
+ }
+ }
+ }
+ return loop_id
+}
+
+fun main() {
+
+ if (arrayloops(listOf(4, 6, 3, 8, 15, 0, 13, 18, 7, 16, 14, 19, 17, 5, 11, 1, 12, 2, 9, 10)) == 3) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (arrayloops(listOf(0, 1, 13, 7, 6, 8, 10, 11, 2, 14, 16, 4, 12, 9, 17, 5, 3, 18, 15, 19)) == 6) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (arrayloops(listOf(9, 8, 3, 11, 5, 7, 13, 19, 12, 4, 14, 10, 18, 2, 16, 1, 0, 15, 6, 17)) == 1) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-236/roger-bell-west/lua/ch-1.lua b/challenge-236/roger-bell-west/lua/ch-1.lua
new file mode 100755
index 0000000000..85014cd27d
--- /dev/null
+++ b/challenge-236/roger-bell-west/lua/ch-1.lua
@@ -0,0 +1,87 @@
+#! /usr/bin/lua
+
+-- by hookenz at
+-- https://stackoverflow.com/questions/9168058/how-to-dump-a-table-to-console
+function dump(o)
+ if type(o) == 'table' then
+ local s = '{ '
+ for k,v in pairs(o) do
+ if type(k) ~= 'number' then k = '"'..k..'"' end
+ s = s .. '['..k..'] = ' .. dump(v) .. ','
+ end
+ return s .. '} '
+ else
+ return tostring(o)
+ end
+end
+
+Reserve = {values = {}, counts = {}, vm = {}}
+
+function Reserve:new(vv)
+ local o = {}
+ self.__index = self
+ setmetatable(o,self)
+ o.values = vv
+ table.sort(o.values, function (aa, bb) return bb < aa end)
+ o.counts = {}
+ o.vm = {}
+ for i, n in ipairs(o.values) do
+ table.insert(o.counts, 0)
+ o.vm[n] = i
+ end
+ return o
+end
+
+function Reserve:makechange(price, tendered)
+ local val = 0
+ for _, note in ipairs(tendered) do
+ if self.vm[note] == nil then
+ return false
+ end
+ self.counts[self.vm[note]] = self.counts[self.vm[note]] + 1
+ val = val + note
+ end
+ if val < price then
+ return false
+ end
+ val = val - price
+ for bid = 1, #self.values do
+ while val >= self.values[bid] and self.counts[bid] > 0 do
+ val = val - self.values[bid]
+ self.counts[bid] = self.counts[bid] - 1
+ end
+ end
+ return (val == 0)
+end
+
+function exactchange(a)
+ local reserve = Reserve:new({5, 10, 20})
+ for _, tendered in ipairs(a) do
+ if not reserve:makechange(5, {tendered}) then
+ return false
+ end
+ end
+ return true
+end
+
+if exactchange({5, 5, 5, 10, 20}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if not exactchange({5, 5, 10, 10, 20}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if exactchange({5, 5, 5, 20}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-236/roger-bell-west/lua/ch-2.lua b/challenge-236/roger-bell-west/lua/ch-2.lua
new file mode 100755
index 0000000000..5dbb9294be
--- /dev/null
+++ b/challenge-236/roger-bell-west/lua/ch-2.lua
@@ -0,0 +1,55 @@
+#! /usr/bin/lua
+
+function arrayloops(a)
+ local loop_id = 0
+ local loops = {}
+ for _i, origin in ipairs(a) do
+ if loops[origin] == nil then
+ local li = 0
+ local thisloop = {}
+ local x = origin
+ while true do
+ if x < 0 or x >= #a then
+ break
+ end
+ thisloop[x] = true
+ x = a[x + 1]
+ if loops[x] ~= nil then
+ li = loops[x]
+ break
+ end
+ if thisloop[x] ~= nil then
+ loop_id = loop_id + 1
+ li = loop_id
+ break
+ end
+ end
+ for i, _t in pairs(thisloop) do
+ loops[i] = li
+ end
+ end
+ end
+ return loop_id
+end
+
+if arrayloops({4, 6, 3, 8, 15, 0, 13, 18, 7, 16, 14, 19, 17, 5, 11, 1, 12, 2, 9, 10}) == 3 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if arrayloops({0, 1, 13, 7, 6, 8, 10, 11, 2, 14, 16, 4, 12, 9, 17, 5, 3, 18, 15, 19}) == 6 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if arrayloops({9, 8, 3, 11, 5, 7, 13, 19, 12, 4, 14, 10, 18, 2, 16, 1, 0, 15, 6, 17}) == 1 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-236/roger-bell-west/perl/ch-1.pl b/challenge-236/roger-bell-west/perl/ch-1.pl
new file mode 100755
index 0000000000..e1c98df3e5
--- /dev/null
+++ b/challenge-236/roger-bell-west/perl/ch-1.pl
@@ -0,0 +1,59 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 3;
+
+is(exactchange([5, 5, 5, 10, 20]), 1, 'example 1');
+is(exactchange([5, 5, 10, 10, 20]), 0, 'example 2');
+is(exactchange([5, 5, 5, 20]), 1, 'example 3');
+
+sub exactchange($a) {
+ my $reserve = Reserve->new([5, 10, 20]);
+ foreach my $tendered (@{$a}) {
+ unless ($reserve->makechange(5, [$tendered])) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+package Reserve;
+
+sub new($class, $init) {
+ my $self = {
+ vall => [sort {$b <=> $a} @{$init}],
+ counts => [(0) x scalar @{$init}],
+ };
+ bless $self, $class;
+ my %vm;
+ foreach my $n (0..$#{$self->{vall}}) {
+ $vm{$self->{vall}[$n]} = $n;
+ }
+ $self->{vm} = \%vm;
+ return $self;
+}
+
+sub makechange($self, $price, $tendered) {
+ my $val = 0;
+ foreach my $note (@{$tendered}) {
+ unless (exists $self->{vm}{$note}) {
+ return 0;
+ }
+ $self->{counts}[$self->{vm}{$note}]++;
+ $val += $note;
+ }
+ if ($val < $price) {
+ return 0;
+ }
+ $val -= $price;
+ foreach my $bid (0..$#{$self->{vall}}) {
+ while ($val >= $self->{vall}[$bid] && $self->{counts}[$bid] > 0) {
+ $val -= $self->{vall}[$bid];
+ $self->{counts}[$bid]--;
+ }
+ }
+ return ($val == 0);
+}
diff --git a/challenge-236/roger-bell-west/perl/ch-2.pl b/challenge-236/roger-bell-west/perl/ch-2.pl
new file mode 100755
index 0000000000..1ef37df3e3
--- /dev/null
+++ b/challenge-236/roger-bell-west/perl/ch-2.pl
@@ -0,0 +1,43 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 3;
+
+is(arrayloops([4, 6, 3, 8, 15, 0, 13, 18, 7, 16, 14, 19, 17, 5, 11, 1, 12, 2, 9, 10]), 3, 'example 1');
+is(arrayloops([0, 1, 13, 7, 6, 8, 10, 11, 2, 14, 16, 4, 12, 9, 17, 5, 3, 18, 15, 19]), 6, 'example 2');
+is(arrayloops([9, 8, 3, 11, 5, 7, 13, 19, 12, 4, 14, 10, 18, 2, 16, 1, 0, 15, 6, 17]), 1, 'example 3');
+
+sub arrayloops($a) {
+ my $loop_id = 0;
+ my %loops;
+ foreach my $origin (0..$#{$a}) {
+ unless (exists $loops{$origin}) {
+ my $li = 0;
+ my %thisloop;
+ my $x = $origin;
+ while (1) {
+ if ($x < 0 || $x > $#{$a}) {
+ last;
+ }
+ $thisloop{$x} = 1;
+ $x = $a->[$x];
+ if (exists $loops{$x}) {
+ $li = $loops{$x};
+ last;
+ }
+ if (exists $thisloop{$x}) {
+ $loop_id++;
+ $li = $loop_id;
+ last;
+ }
+ }
+ foreach my $i (keys %thisloop) {
+ $loops{$i} = $li;
+ }
+ }
+ }
+ return $loop_id;
+}
diff --git a/challenge-236/roger-bell-west/postscript/ch-1.ps b/challenge-236/roger-bell-west/postscript/ch-1.ps
new file mode 100644
index 0000000000..b2cb52dcd6
--- /dev/null
+++ b/challenge-236/roger-bell-west/postscript/ch-1.ps
@@ -0,0 +1,221 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/quicksort.cmp {
+ 2 copy
+ lt {
+ pop pop -1
+ } {
+ gt {
+ 1
+ } {
+ 0
+ } ifelse
+ } ifelse
+} bind def
+
+/quicksort.main { % lo hi -> (null)
+ 3 dict begin
+ /hi exch def
+ /lo exch def
+ /xit false def
+ lo 0 lt {
+ /xit true def
+ } if
+ hi 0 lt {
+ /xit true def
+ } if
+ lo hi ge {
+ /xit true def
+ } if
+ xit not {
+ /p quicksort.partition def
+ lo p quicksort.main
+ p 1 add hi quicksort.main
+ } if
+ end
+} bind def
+
+/quicksort {
+ { quicksort.cmp } quicksort.with_comparator
+} bind def
+
+/test.start {
+ print (:) print
+ /test.pass 0 def
+ /test.count 0 def
+} bind def
+
+/quicksort.partition {
+ 3 dict begin
+ /pivot arr hi lo add 2 idiv get def
+ /i lo 1 sub def
+ /j hi 1 add def
+ {
+ {
+ /i i 1 add def
+ arr i get pivot cmp 0 ge {
+ exit
+ } if
+ } loop
+ {
+ /j j 1 sub def
+ arr j get pivot cmp 0 le {
+ exit
+ } if
+ } loop
+ i j ge {
+ j
+ exit
+ } if
+ i j quicksort.swap
+ } loop
+ end
+} bind def
+
+/quicksort.swap {
+ 2 dict begin
+ /bi exch def
+ /ai exch def
+ arr ai get
+ arr bi get
+ arr exch ai exch put
+ arr exch bi exch put
+ end
+} bind def
+
+/quicksort.with_comparator { % [ a c b ] { comparator } -> [ a b c ]
+ 2 dict begin
+ /cmp exch def
+ /arr exch def
+ arr length 0 gt {
+ 0 arr length 1 sub quicksort.main
+ } if
+ arr
+ end
+} bind def
+
+/test {
+ /test.count test.count 1 add def
+ {
+ /test.pass test.pass 1 add def
+ } {
+ ( ) print
+ test.count (....) cvs print
+ (-fail) print
+ } ifelse
+} bind def
+
+/test.end {
+ ( ) print
+ test.count 0 gt {
+ (Passed ) print
+ test.pass (...) cvs print
+ (/) print
+ test.count (...) cvs print
+ ( \() print
+ test.pass 100 mul test.count idiv (...) cvs print
+ (%\)) print
+ (\r\n) print
+ } if
+} bind def
+
+/reverse {
+ 1 dict begin
+ dup length /l exch def
+ [ exch
+ aload pop
+ 2 1 l {
+ -1 roll
+ } for
+ ]
+ end
+} bind def
+
+
+% end included library code
+
+/reserve.new {
+ 0 dict begin
+ /self 3 dict def
+ quicksort reverse self exch /values exch put
+ self /counts [ self (values) get length { 0 } repeat ] put
+ /vm self (values) get length dict def
+ 0 1 self (values) get length 1 sub {
+ dup
+ self (values) get exch get
+ exch
+ vm 3 1 roll
+ put
+ } for
+ self (vm) vm put
+ self
+ end
+} bind def
+
+/reserve.makechange {
+ 0 dict begin
+ /tendered exch def
+ /price exch def
+ /self exch def
+ /val 0 def
+ true
+ 1 {
+ tendered {
+ /note exch def
+ self (vm) get note known not {
+ pop false
+ exit
+ } if
+ self (counts) get self (vm) get note get get 1 add
+ self (counts) get self (vm) get note get 3 -1 roll put
+ /val val note add def
+ } forall
+ dup not {
+ exit
+ } if
+ val price lt {
+ pop false
+ exit
+ } if
+ /val val price sub def
+ 0 1 self (values) get length 1 sub {
+ /bid exch def
+ {
+ val self (values) get bid get lt {
+ exit
+ } if
+ self (counts) get bid get 0 le {
+ exit
+ } if
+ /val val self (values) get bid get sub def
+ self (counts) get dup bid get 1 sub bid exch put
+ } loop
+ } for
+ } repeat
+ val 0 eq and
+ end
+} bind def
+
+/exactchange {
+ 0 dict begin
+ /reserve [5 10 20] reserve.new def
+ true exch
+ {
+ /tendered exch def
+ reserve 5 [ tendered ] reserve.makechange not {
+ pop false
+ exit
+ } if
+ } forall
+ end
+} bind def
+
+[ 5 10 20 ] reserve.new
+
+(exactchange) test.start
+[5 5 5 10 20] exactchange test
+[5 5 10 10 20] exactchange not test
+[5 5 5 20] exactchange test
+test.end
diff --git a/challenge-236/roger-bell-west/postscript/ch-2.ps b/challenge-236/roger-bell-west/postscript/ch-2.ps
new file mode 100644
index 0000000000..45b04c6137
--- /dev/null
+++ b/challenge-236/roger-bell-west/postscript/ch-2.ps
@@ -0,0 +1,87 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/keys { % dict -> array of dict keys
+ [ exch
+ {
+ pop
+ } forall
+ ]
+} bind def
+
+/test.end {
+ ( ) print
+ test.count 0 gt {
+ (Passed ) print
+ test.pass (...) cvs print
+ (/) print
+ test.count (...) cvs print
+ ( \() print
+ test.pass 100 mul test.count idiv (...) cvs print
+ (%\)) print
+ (\r\n) print
+ } if
+} bind def
+
+/test.start {
+ print (:) print
+ /test.pass 0 def
+ /test.count 0 def
+} bind def
+
+/test {
+ /test.count test.count 1 add def
+ {
+ /test.pass test.pass 1 add def
+ } {
+ ( ) print
+ test.count (....) cvs print
+ (-fail) print
+ } ifelse
+} bind def
+
+
+% end included library code
+
+/arrayloops {
+ 0 dict begin
+ /a exch def
+ /loop_id 0 def
+ /loops 0 dict def
+ a {
+ /origin exch def
+ loops origin known not {
+ /li 0 def
+ /thisloop 0 dict def
+ /x origin def
+ {
+ x 0 lt x a length ge or {
+ exit
+ } if
+ thisloop x true put
+ /x a x get def
+ loops x known {
+ /li loops x get def
+ exit
+ } if
+ thisloop x known {
+ /loop_id loop_id 1 add def
+ /li loop_id def
+ exit
+ } if
+ } loop
+ thisloop keys {
+ loops exch li put
+ } forall
+ } if
+ } forall
+ loop_id
+ end
+} bind def
+
+(arrayloops) test.start
+[4 6 3 8 15 0 13 18 7 16 14 19 17 5 11 1 12 2 9 10] arrayloops 3 eq test
+[0 1 13 7 6 8 10 11 2 14 16 4 12 9 17 5 3 18 15 19] arrayloops 6 eq test
+[9 8 3 11 5 7 13 19 12 4 14 10 18 2 16 1 0 15 6 17] arrayloops 1 eq test
+test.end
diff --git a/challenge-236/roger-bell-west/python/ch-1.py b/challenge-236/roger-bell-west/python/ch-1.py
new file mode 100755
index 0000000000..638c1ca054
--- /dev/null
+++ b/challenge-236/roger-bell-west/python/ch-1.py
@@ -0,0 +1,49 @@
+#! /usr/bin/python3
+
+class Reserve(object):
+ def __init__(self, _vv):
+ _vq = _vv
+ _vq.sort()
+ _vq.reverse()
+ _vm = dict()
+ for i, v in enumerate(_vq):
+ _vm[v] = i
+ self.values = _vq
+ self.counts = [0] * len(_vv)
+ self.vm = _vm
+
+ def makechange(self, price, tendered):
+ val = 0
+ for bill in tendered:
+ if bill not in self.vm:
+ return False
+ self.counts[self.vm.get(bill)] += 1
+ val += bill
+ val -= price
+ for bid in range(len(self.values)):
+ while val >= self.values[bid] and self.counts[bid] > 0:
+ val -= self.values[bid]
+ self.counts[bid] -= 1
+ return (val == 0)
+
+def exactchange(a):
+ reserve = Reserve([5, 10, 20])
+ for tendered in a:
+ if not reserve.makechange(5, [tendered]):
+ return False
+ return True
+
+import unittest
+
+class TestExactchange(unittest.TestCase):
+
+ def test_ex1(self):
+ self.assertEqual(exactchange([5, 5, 5, 10, 20]), True, 'example 1')
+
+ def test_ex2(self):
+ self.assertEqual(exactchange([5, 5, 10, 10, 20]), False, 'example 2')
+
+ def test_ex3(self):
+ self.assertEqual(exactchange([5, 5, 5, 20]), True, 'example 3')
+
+unittest.main()
diff --git a/challenge-236/roger-bell-west/python/ch-2.py b/challenge-236/roger-bell-west/python/ch-2.py
new file mode 100755
index 0000000000..d00cdd365a
--- /dev/null
+++ b/challenge-236/roger-bell-west/python/ch-2.py
@@ -0,0 +1,40 @@
+#! /usr/bin/python3
+
+def arrayloops(a):
+ loop_id = 0
+ loops = dict()
+ for origin in range(len(a)):
+ if origin not in loops:
+ li = 0
+ thisloop = set()
+ x = origin
+ while True:
+ if x < 0 or x >= len(a):
+ break
+ thisloop.add(x)
+ x = a[x]
+ if x in loops:
+ li = loops[x]
+ break
+ if x in thisloop:
+ loop_id += 1
+ li = loop_id
+ break
+ for i in thisloop:
+ loops[i] = li
+ return loop_id
+
+import unittest
+
+class TestArrayloops(unittest.TestCase):
+
+ def test_ex1(self):
+ self.assertEqual(arrayloops([4, 6, 3, 8, 15, 0, 13, 18, 7, 16, 14, 19, 17, 5, 11, 1, 12, 2, 9, 10]), 3, 'example 1')
+
+ def test_ex2(self):
+ self.assertEqual(arrayloops([0, 1, 13, 7, 6, 8, 10, 11, 2, 14, 16, 4, 12, 9, 17, 5, 3, 18, 15, 19]), 6, 'example 2')
+
+ def test_ex3(self):
+ self.assertEqual(arrayloops([9, 8, 3, 11, 5, 7, 13, 19, 12, 4, 14, 10, 18, 2, 16, 1, 0, 15, 6, 17]), 1, 'example 3')
+
+unittest.main()
diff --git a/challenge-236/roger-bell-west/raku/ch-1.p6 b/challenge-236/roger-bell-west/raku/ch-1.p6
new file mode 100755
index 0000000000..cafe4c4b6d
--- /dev/null
+++ b/challenge-236/roger-bell-west/raku/ch-1.p6
@@ -0,0 +1,56 @@
+#! /usr/bin/raku
+
+use Test;
+
+plan 3;
+
+is(exactchange([5, 5, 5, 10, 20]), True, 'example 1');
+is(exactchange([5, 5, 10, 10, 20]), False, 'example 2');
+is(exactchange([5, 5, 5, 20]), True, 'example 3');
+
+class Reserve {
+ has @!values;
+ has @!counts;
+ has %!vm;
+
+ method TWEAK(:@notes) {
+ my @vq = @notes.sort({$^b <=> $^a});
+ for (0..@vq.end) -> $i {
+ %!vm{@vq[$i]} = $i;
+ }
+ @!values = @vq;
+ @!counts = 0 xx @vq.elems;
+ }
+
+ method makechange($price, @tendered) {
+ my $val = 0;
+ for @tendered -> $note {
+ unless (%!vm{$note}:exists) {
+ return False;
+ }
+ @!counts[%!vm{$note}]++;
+ $val += $note;
+ }
+ if ($val < $price) {
+ return False;
+ }
+ $val -= $price;
+ for 0..@!values.end -> $bid {
+ while ($val >= @!values[$bid] && @!counts[$bid] > 0) {
+ $val -= @!values[$bid];
+ @!counts[$bid]--;
+ }
+ }
+ return ($val == 0);
+ }
+}
+
+sub exactchange(@a) {
+ my $reserve = Reserve.new(notes => [5, 10, 20]);
+ for @a -> $tendered {
+ unless ($reserve.makechange(5, [$tendered])) {
+ return False;
+ }
+ }
+ return True;
+}
diff --git a/challenge-236/roger-bell-west/raku/ch-2.p6 b/challenge-236/roger-bell-west/raku/ch-2.p6
new file mode 100755
index 0000000000..95a5128639
--- /dev/null
+++ b/