aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Bell_West <roger@firedrake.org>2025-05-21 10:35:51 +0100
committerRoger Bell_West <roger@firedrake.org>2025-05-21 10:35:51 +0100
commitc98269294e86c9c9cbf409de378e34039b2e20c8 (patch)
tree0e7dd5d958278b14f4058823c853a80b201e3eef
parentaaaa94bd6d0f97e4d2ec2abe62588d264491afca (diff)
downloadperlweeklychallenge-club-c98269294e86c9c9cbf409de378e34039b2e20c8.tar.gz
perlweeklychallenge-club-c98269294e86c9c9cbf409de378e34039b2e20c8.tar.bz2
perlweeklychallenge-club-c98269294e86c9c9cbf409de378e34039b2e20c8.zip
RogerBW solutions for challenge no. 322
-rwxr-xr-xchallenge-322/roger-bell-west/crystal/ch-1.cr31
-rwxr-xr-xchallenge-322/roger-bell-west/crystal/ch-2.cr27
-rwxr-xr-xchallenge-322/roger-bell-west/javascript/ch-1.js39
-rwxr-xr-xchallenge-322/roger-bell-west/javascript/ch-2.js65
-rw-r--r--challenge-322/roger-bell-west/kotlin/ch-1.kt39
-rw-r--r--challenge-322/roger-bell-west/kotlin/ch-2.kt35
-rwxr-xr-xchallenge-322/roger-bell-west/lua/ch-1.lua61
-rwxr-xr-xchallenge-322/roger-bell-west/lua/ch-2.lua78
-rwxr-xr-xchallenge-322/roger-bell-west/perl/ch-1.pl28
-rwxr-xr-xchallenge-322/roger-bell-west/perl/ch-2.pl24
-rw-r--r--challenge-322/roger-bell-west/postscript/ch-1.ps107
-rw-r--r--challenge-322/roger-bell-west/postscript/ch-2.ps234
-rwxr-xr-xchallenge-322/roger-bell-west/python/ch-1.py29
-rwxr-xr-xchallenge-322/roger-bell-west/python/ch-2.py27
-rwxr-xr-xchallenge-322/roger-bell-west/raku/ch-1.p626
-rwxr-xr-xchallenge-322/roger-bell-west/raku/ch-2.p622
-rwxr-xr-xchallenge-322/roger-bell-west/ruby/ch-1.rb36
-rwxr-xr-xchallenge-322/roger-bell-west/ruby/ch-2.rb34
-rwxr-xr-xchallenge-322/roger-bell-west/rust/ch-1.rs34
-rwxr-xr-xchallenge-322/roger-bell-west/rust/ch-2.rs34
-rw-r--r--challenge-322/roger-bell-west/scala/ch-1.scala40
-rw-r--r--challenge-322/roger-bell-west/scala/ch-2.scala38
-rw-r--r--challenge-322/roger-bell-west/tests.json44
-rw-r--r--challenge-322/roger-bell-west/typst/ch-1.typ34
-rw-r--r--challenge-322/roger-bell-west/typst/ch-2.typ33
25 files changed, 1199 insertions, 0 deletions
diff --git a/challenge-322/roger-bell-west/crystal/ch-1.cr b/challenge-322/roger-bell-west/crystal/ch-1.cr
new file mode 100755
index 0000000000..114f892092
--- /dev/null
+++ b/challenge-322/roger-bell-west/crystal/ch-1.cr
@@ -0,0 +1,31 @@
+#! /usr/bin/crystal
+
+def formatstring(a, n)
+ p = a.chars.select{|x| x != '-'}
+ r = p.size % n
+ if r == 0
+ r += n
+ end
+ o = ""
+ p.each_with_index do |c, i|
+ if r == i
+ o += '-'
+ r += n
+ end
+ o += c
+ end
+ o
+end
+
+require "spec"
+describe "formatstring" do
+ it "test_ex1" do
+ formatstring("ABC-D-E-F", 3).should eq "ABC-DEF"
+ end
+ it "test_ex2" do
+ formatstring("A-BC-D-E", 2).should eq "A-BC-DE"
+ end
+ it "test_ex3" do
+ formatstring("-A-B-CD-E", 4).should eq "A-BCDE"
+ end
+end
diff --git a/challenge-322/roger-bell-west/crystal/ch-2.cr b/challenge-322/roger-bell-west/crystal/ch-2.cr
new file mode 100755
index 0000000000..ea621c8863
--- /dev/null
+++ b/challenge-322/roger-bell-west/crystal/ch-2.cr
@@ -0,0 +1,27 @@
+#! /usr/bin/crystal
+
+def rankarray(a)
+ b = a.to_set.to_a.sort
+ c = Hash(Int32, Int32).new
+ b.each_with_index do |n, i|
+ c[n] = i + 1
+ end
+ out = Array(Int32).new
+ a.each do |v|
+ out.push(c[v])
+ end
+ out
+end
+
+require "spec"
+describe "rankarray" do
+ it "test_ex1" do
+ rankarray([55, 22, 44, 33]).should eq [4, 1, 3, 2]
+ end
+ it "test_ex2" do
+ rankarray([10, 10, 10]).should eq [1, 1, 1]
+ end
+ it "test_ex3" do
+ rankarray([5, 1, 1, 4, 3]).should eq [4, 1, 1, 3, 2]
+ end
+end
diff --git a/challenge-322/roger-bell-west/javascript/ch-1.js b/challenge-322/roger-bell-west/javascript/ch-1.js
new file mode 100755
index 0000000000..dd374de26a
--- /dev/null
+++ b/challenge-322/roger-bell-west/javascript/ch-1.js
@@ -0,0 +1,39 @@
+#! /usr/bin/node
+
+"use strict"
+
+function formatstring(a, n) {
+ const p = a.split("").filter(x => x != '-');
+ let r = p.length % n;
+ if (r == 0) {
+ r += n;
+ }
+ let o = "";
+ p.forEach((c, i) => {
+ if (r == i) {
+ o += '-';
+ r += n;
+ }
+ o += c;
+ });
+ return o;
+}
+
+if (formatstring('ABC-D-E-F', 3) == 'ABC-DEF') {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (formatstring('A-BC-D-E', 2) == 'A-BC-DE') {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (formatstring('-A-B-CD-E', 4) == 'A-BCDE') {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-322/roger-bell-west/javascript/ch-2.js b/challenge-322/roger-bell-west/javascript/ch-2.js
new file mode 100755
index 0000000000..6aab292711
--- /dev/null
+++ b/challenge-322/roger-bell-west/javascript/ch-2.js
@@ -0,0 +1,65 @@
+#! /usr/bin/node
+
+"use strict"
+
+// by Frank Tan
+// https://stackoverflow.com/questions/38400594/javascript-deep-comparison
+function deepEqual(a,b)
+{
+ if( (typeof a == 'object' && a != null) &&
+ (typeof b == 'object' && b != null) )
+ {
+ var count = [0,0];
+ for( var key in a) count[0]++;
+ for( var key in b) count[1]++;
+ if( count[0]-count[1] != 0) {return false;}
+ for( var key in a)
+ {
+ if(!(key in b) || !deepEqual(a[key],b[key])) {return false;}
+ }
+ for( var key in b)
+ {
+ if(!(key in a) || !deepEqual(b[key],a[key])) {return false;}
+ }
+ return true;
+ }
+ else
+ {
+ return a === b;
+ }
+}
+
+function rankarray(a) {
+ const b = Array.from(new Set(a));
+ b.sort(function(p, q) {
+ return p - q;
+ });
+ let c = new Map();
+ b.forEach((n, i) => {
+ c.set(n, i + 1);
+ });
+ let out = [];
+ for (let v of a) {
+ out.push(c.get(v));
+ }
+ return out;
+}
+
+if (deepEqual(rankarray([55, 22, 44, 33]), [4, 1, 3, 2])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(rankarray([10, 10, 10]), [1, 1, 1])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(rankarray([5, 1, 1, 4, 3]), [4, 1, 1, 3, 2])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-322/roger-bell-west/kotlin/ch-1.kt b/challenge-322/roger-bell-west/kotlin/ch-1.kt
new file mode 100644
index 0000000000..8fb53e62fb
--- /dev/null
+++ b/challenge-322/roger-bell-west/kotlin/ch-1.kt
@@ -0,0 +1,39 @@
+fun formatstring(a: String, n: Int): String {
+ val p = a.toCharArray().filter{it != '-'}
+ var r = p.size % n
+ if (r == 0) {
+ r += n
+ }
+ var o =""
+ p.forEachIndexed {i, c ->
+ if (r == i) {
+ o += '-'
+ r += n
+ }
+ o += c
+ }
+ return o
+}
+
+fun main() {
+
+ if (formatstring("ABC-D-E-F", 3) == "ABC-DEF") {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (formatstring("A-BC-D-E", 2) == "A-BC-DE") {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (formatstring("-A-B-CD-E", 4) == "A-BCDE") {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-322/roger-bell-west/kotlin/ch-2.kt b/challenge-322/roger-bell-west/kotlin/ch-2.kt
new file mode 100644
index 0000000000..8400537f94
--- /dev/null
+++ b/challenge-322/roger-bell-west/kotlin/ch-2.kt
@@ -0,0 +1,35 @@
+fun rankarray(a: List<Int>): List<Int> {
+ val b =a.toSet().toList().sorted()
+ var c = mutableMapOf<Int, Int>()
+ b.forEachIndexed {i, n ->
+ c[n] = i + 1
+ }
+ var out = ArrayList<Int>()
+ for (v in a) {
+ out.add(c.getValue(v))
+ }
+ return out.toList()
+}
+
+fun main() {
+
+ if (rankarray(listOf(55, 22, 44, 33)) == listOf(4, 1, 3, 2)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (rankarray(listOf(10, 10, 10)) == listOf(1, 1, 1)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (rankarray(listOf(5, 1, 1, 4, 3)) == listOf(4, 1, 1, 3, 2)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-322/roger-bell-west/lua/ch-1.lua b/challenge-322/roger-bell-west/lua/ch-1.lua
new file mode 100755
index 0000000000..afed8c9ba5
--- /dev/null
+++ b/challenge-322/roger-bell-west/lua/ch-1.lua
@@ -0,0 +1,61 @@
+#! /usr/bin/lua
+
+function filter(seq, func)
+ local out = {}
+ for _, x in ipairs(seq) do
+ if func(x) then
+ table.insert(out, x)
+ end
+ end
+ return out
+end
+
+function split(t)
+ local cl = {}
+ string.gsub(t,
+ "(.)",
+ function(c)
+ table.insert(cl, c)
+ end
+ )
+ return cl
+end
+
+function formatstring(a, n)
+ local p = filter(split(a), function(a) return a ~= "-" end)
+ local r = #p % n + 1
+ if r == 1 then
+ r = r + n
+ end
+ local o = ""
+ for i, c in ipairs(p) do
+ if r == i then
+ o = o .. "-"
+ r = r + n
+ end
+ o = o .. c
+ end
+ return o
+end
+
+if formatstring("ABC-D-E-F", 3) == "ABC-DEF" then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if formatstring("A-BC-D-E", 2) == "A-BC-DE" then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if formatstring("-A-B-CD-E", 4) == "A-BCDE" then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-322/roger-bell-west/lua/ch-2.lua b/challenge-322/roger-bell-west/lua/ch-2.lua
new file mode 100755
index 0000000000..45142fcb13
--- /dev/null
+++ b/challenge-322/roger-bell-west/lua/ch-2.lua
@@ -0,0 +1,78 @@
+#! /usr/bin/lua
+
+-- by Michael Anderson at
+-- https://stackoverflow.com/questions/8722620/comparing-two-index-tables-by-index-value-in-lua
+-- modified by Roger
+function recursive_compare(t1,t2)
+ -- Use usual comparison first.
+ if t1==t2 then return true end
+ -- We only support non-default behavior for tables
+ if (type(t1)~="table") then return false end
+ -- They better have the same metatables
+ local mt1 = getmetatable(t1)
+ local mt2 = getmetatable(t2)
+ if( not recursive_compare(mt1,mt2) ) then return false end
+ -- Build list of all keys
+ local kk = {}
+ for k1, _ in pairs(t1) do
+ kk[k1] = true
+ end
+ for k2, _ in pairs(t2) do
+ kk[k2] = true
+ end
+ -- Check each key that exists in at least one table
+ for _, k in ipairs(kk) do
+ if (not recursive_compare(t1[k], t2[k])) then
+ return false
+ end
+ end
+ return true
+end
+
+function keys(t)
+ local a = {}
+ for k, v in pairs(t) do
+ table.insert(a, k)
+ end
+ return a
+end
+
+function rankarray(a)
+ local k = {}
+ for _, c in ipairs(a) do
+ k[c] = true
+ end
+ local b = keys(k)
+ table.sort(b)
+ local c = {}
+ for i, n in ipairs(b) do
+ c[n] = i
+ end
+ local out = {}
+ for _, v in ipairs(a) do
+ table.insert(out, c[v])
+ end
+ return out
+end
+
+if recursive_compare(rankarray({55, 22, 44, 33}), {4, 1, 3, 2}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(rankarray({10, 10, 10}), {1, 1, 1}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(rankarray({5, 1, 1, 4, 3}), {4, 1, 1, 3, 2}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-322/roger-bell-west/perl/ch-1.pl b/challenge-322/roger-bell-west/perl/ch-1.pl
new file mode 100755
index 0000000000..1318912f2d
--- /dev/null
+++ b/challenge-322/roger-bell-west/perl/ch-1.pl
@@ -0,0 +1,28 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 3;
+
+is(formatstring('ABC-D-E-F', 3), 'ABC-DEF', 'example 1');
+is(formatstring('A-BC-D-E', 2), 'A-BC-DE', 'example 2');
+is(formatstring('-A-B-CD-E', 4), 'A-BCDE', 'example 3');
+
+sub formatstring($a, $n) {
+ my @p = grep {$_ ne '-'} split '',$a;
+ my $r = scalar @p % $n;
+ if ($r == 0) {
+ $r += $n;
+ }
+ my $o;
+ while (my ($i, $c) = each @p) {
+ if ($r == $i) {
+ $o .= '-';
+ $r += $n;
+ }
+ $o .= $c;
+ }
+ $o;
+}
diff --git a/challenge-322/roger-bell-west/perl/ch-2.pl b/challenge-322/roger-bell-west/perl/ch-2.pl
new file mode 100755
index 0000000000..af518cc3c4
--- /dev/null
+++ b/challenge-322/roger-bell-west/perl/ch-2.pl
@@ -0,0 +1,24 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 3;
+
+is_deeply(rankarray([55, 22, 44, 33]), [4, 1, 3, 2], 'example 1');
+is_deeply(rankarray([10, 10, 10]), [1, 1, 1], 'example 2');
+is_deeply(rankarray([5, 1, 1, 4, 3]), [4, 1, 1, 3, 2], 'example 3');
+
+sub rankarray($a) {
+ my @b = sort {$::a <=> $::b} keys %{{map {$_ => 1} @{$a}}};
+ my %c;
+ while (my ($i, $n) = each @b) {
+ $c{$n} = $i + 1;
+ }
+ my @out;
+ foreach my $v (@{$a}) {
+ push @out, $c{$v};
+ }
+ \@out;
+}
diff --git a/challenge-322/roger-bell-west/postscript/ch-1.ps b/challenge-322/roger-bell-west/postscript/ch-1.ps
new file mode 100644
index 0000000000..76bc5b0c8f
--- /dev/null
+++ b/challenge-322/roger-bell-west/postscript/ch-1.ps
@@ -0,0 +1,107 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/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
+
+/enumerate.array {
+ 1 dict begin
+ /a exch def
+ [
+ 0 1 a length 1 sub {
+ [ exch dup a exch get ]
+ } for
+ ]
+ end
+} 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
+
+/a2s {
+ 2 dict begin
+ /i exch def
+ i length dup string /o exch def
+ 1 sub 0 exch 1 exch {
+ dup i 3 -1 roll get o 3 1 roll put
+ } for
+ o
+ end
+} bind def
+
+/filter { % array proc(bool) -> array
+ 1 dict begin
+ /p exch def
+ [ exch
+ {
+ dup p not
+ {
+ pop
+ } if
+ } forall
+ ]
+ end
+} bind def
+
+/s2a {
+ [ exch { } forall ]
+} bind def
+
+
+% end included library code
+
+/formatstring {
+ 0 dict begin
+ /n exch def
+ s2a { 16#2D ne } filter /p exch def
+ /r p length n mod def
+ r 0 eq {
+ /r r n add def
+ } if
+ [
+ p enumerate.array {
+ aload pop
+ /c exch def
+ /i exch def
+ r i eq {
+ 16#2D
+ /r r n add def
+ } if
+ c
+ } forall
+ ]
+ a2s
+ end
+} bind def
+
+(formatstring) test.start
+(ABC-D-E-F) 3 formatstring (ABC-DEF) eq test
+(A-BC-D-E) 2 formatstring (A-BC-DE) eq test
+(-A-B-CD-E) 4 formatstring (A-BCDE) eq test
+test.end
diff --git a/challenge-322/roger-bell-west/postscript/ch-2.ps b/challenge-322/roger-bell-west/postscript/ch-2.ps
new file mode 100644
index 0000000000..f992bc5d50
--- /dev/null
+++ b/challenge-322/roger-bell-west/postscript/ch-2.ps
@@ -0,0 +1,234 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/toset { % array -> dict of (value, true)
+ << exch
+ {
+ true
+ } forall
+ >>
+} 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
+
+/quicksort.cmp {
+ 2 copy
+ lt {
+ pop pop -1
+ } {
+ gt {
+ 1
+ } {
+ 0
+ } ifelse
+ } ifelse
+} bind def
+
+/keys { % dict -> array of dict keys
+ [ exch
+ {
+ pop
+ } forall
+ ]
+} bind def
+
+/quicksort {
+ { quicksort.cmp } quicksort.with_comparator
+} bind def
+
+/deepeq {
+ 2 dict begin
+ /a exch def
+ /b exch def
+ a type b type eq {
+ a type /dicttype eq {
+ a length b length eq {
+ <<
+ a {
+ pop
+ true
+ } forall
+ b {
+ pop
+ true
+ } forall
+ >>
+ true exch
+ {
+ pop
+ dup a exch known {
+ dup b exch known {
+ dup a exch get exch b exch get deepeq not {
+ pop false
+ } if
+ } {
+ false
+ } ifelse
+ } {
+ false
+ } ifelse
+ } forall
+ } {
+ false
+ } ifelse
+ } {
+ a type dup /arraytype eq exch /stringtype eq or {
+ a length b length eq {
+ true
+ 0 1 a length 1 sub {
+ dup a exch get exch b exch get deepeq not {
+ pop false
+ exit
+ } if
+ } for
+ } {
+ false
+ } ifelse
+ } {
+ a b eq
+ } ifelse
+ } ifelse
+ } {
+ false
+ } ifelse
+ end
+} 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
+
+/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.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
+
+/enumerate.array {
+ 1 dict begin
+ /a exch def
+ [
+ 0 1 a length 1 sub {
+ [ exch dup a exch get ]
+ } for
+ ]
+ 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
+
+/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
+
+/rankarray {
+ 0 dict begin
+ /a exch def
+ /c 0 dict def
+ a toset keys quicksort enumerate.array {
+ aload pop
+ /n exch def
+ /i exch def
+ c n i 1 add put
+ } forall
+ [
+ a {
+ c exch get
+ } forall
+ ]
+ end
+} bind def
+
+(rankarray) test.start
+[55 22 44 33] rankarray [4 1 3 2] deepeq test
+[10 10 10] rankarray [1 1 1] deepeq test
+[5 1 1 4 3] rankarray [4 1 1 3 2] deepeq test
+test.end
diff --git a/challenge-322/roger-bell-west/python/ch-1.py b/challenge-322/roger-bell-west/python/ch-1.py
new file mode 100755
index 0000000000..4e052cc13c
--- /dev/null
+++ b/challenge-322/roger-bell-west/python/ch-1.py
@@ -0,0 +1,29 @@
+#! /usr/bin/python3
+
+def formatstring(a, n):
+ p = [c for c in a if c != '-']
+ r = len(p) % n
+ if r == 0:
+ r += n
+ o = ""
+ for i, c in enumerate(p):
+ if r == i:
+ o += '-'
+ r += n
+ o += c
+ return o
+
+import unittest
+
+class TestFormatstring(unittest.TestCase):
+
+ def test_ex1(self):
+ self.assertEqual(formatstring("ABC-D-E-F", 3), "ABC-DEF", 'example 1')
+
+ def test_ex2(self):
+ self.assertEqual(formatstring("A-BC-D-E", 2), "A-BC-DE", 'example 2')
+
+ def test_ex3(self):
+ self.assertEqual(formatstring("-A-B-CD-E", 4), "A-BCDE", 'example 3')
+
+unittest.main()
diff --git a/challenge-322/roger-bell-west/python/ch-2.py b/challenge-322/roger-bell-west/python/ch-2.py
new file mode 100755
index 0000000000..f0837afc54
--- /dev/null
+++ b/challenge-322/roger-bell-west/python/ch-2.py
@@ -0,0 +1,27 @@
+#! /usr/bin/python3
+
+def rankarray(a):
+ b = list(set(a))
+ b.sort()
+ c = dict()
+ for i, n in enumerate(b):
+ c[n] = i + 1
+ out = []
+ for v in a:
+ out.append(c[v])
+ return out
+
+import unittest
+
+class TestRankarray(unittest.TestCase):
+
+ def test_ex1(self):
+ self.assertEqual(rankarray([55, 22, 44, 33]), [4, 1, 3, 2], 'example 1')
+
+ def test_ex2(self):
+ self.assertEqual(rankarray([10, 10, 10]), [1, 1, 1], 'example 2')
+
+ def test_ex3(self):
+ self.assertEqual(rankarray([5, 1, 1, 4, 3]), [4, 1, 1, 3, 2], 'example 3')
+
+unittest.main()
diff --git a/challenge-322/roger-bell-west/raku/ch-1.p6 b/challenge-322/roger-bell-west/raku/ch-1.p6
new file mode 100755
index 0000000000..26d0d35763
--- /dev/null
+++ b/challenge-322/roger-bell-west/raku/ch-1.p6
@@ -0,0 +1,26 @@
+#! /usr/bin/raku
+
+use Test;
+
+plan 3;
+
+is(formatstring('ABC-D-E-F', 3), 'ABC-DEF', 'example 1');
+is(formatstring('A-BC-D-E', 2), 'A-BC-DE', 'example 2');
+is(formatstring('-A-B-CD-E', 4), 'A-BCDE', 'example 3');
+
+sub formatstring($a, $n) {
+ my @p = $a.comb.grep({$_ ne '-'});
+ my $r = @p.elems % $n;
+ if ($r == 0) {
+ $r += $n;
+ }
+ my $o;
+ for @p.kv -> $i, $c {
+ if ($r == $i) {
+ $o ~= '-';
+ $r += $n;
+ }
+ $o ~= $c;
+ }
+ $o;
+}
diff --git a/challenge-322/roger-bell-west/raku/ch-2.p6 b/challenge-322/roger-bell-west/raku/ch-2.p6
new file mode 100755
index 0000000000..b0b46fd0d6
--- /dev/null
+++ b/challenge-322/roger-bell-west/raku/ch-2.p6
@@ -0,0 +1,22 @@
+#! /usr/bin/raku
+
+use Test;
+
+plan 3;
+
+is-deeply(rankarray([55, 22, 44, 33]), [4, 1, 3, 2], 'example 1');
+is-deeply(rankarray([10, 10, 10]), [1, 1, 1], 'example 2');
+is-deeply(rankarray([5, 1, 1, 4, 3]), [4, 1, 1, 3, 2], 'example 3');
+
+sub rankarray(@a) {
+ my @b = Set.new(@a).keys.sort({ $^a <=> $^b });
+ my %c;
+ for @b.kv -> $i, $n {
+ %c{$n} = $i + 1;
+ }
+ my @out;
+ for @a -> $v {
+ @out.push(%c{$v});
+ }
+ @out;
+}
diff --git a/challenge-322/roger-bell-west/ruby/ch-1.rb b/challenge-322/roger-bell-west/ruby/ch-1.rb
new file mode 100755
index 0000000000..14173f9fb1
--- /dev/null
+++ b/challenge-322/roger-bell-west/ruby/ch-1.rb
@@ -0,0 +1,36 @@
+#! /usr/bin/ruby
+
+def formatstring(a, n)
+ p = a.chars.select{|x| x != '-'}
+ r = p.size % n
+ if r == 0
+ r += n
+ end
+ o = ""
+ p.each_with_index do |c, i|
+ if r == i
+ o += '-'
+ r += n
+ end
+ o += c
+ end
+ o
+end
+
+require 'test/unit'
+
+class TestFormatstring < Test::Unit::TestCase
+
+ def test_ex1
+ assert_equal('ABC-DEF', formatstring('ABC-D-E-F', 3))
+ end
+
+ def test_ex2
+ assert_equal('A-BC-DE', formatstring('A-BC-D-E', 2))
+ end
+
+ def test_ex3
+ assert_equal('A-BCDE', formatstring('-A-B-CD-E', 4))
+ end
+
+end
diff --git a/challenge-322/roger-bell-west/ruby/ch-2.rb b/challenge-322/roger-bell-west/ruby/ch-2.rb
new file mode 100755
index 0000000000..c6f835a63c
--- /dev/null
+++ b/challenge-322/roger-bell-west/ruby/ch-2.rb
@@ -0,0 +1,34 @@
+#! /usr/bin/ruby
+
+require 'set'
+
+def rankarray(a)
+ b = a.to_set.to_a.sort
+ c = {}
+ b.each_with_index do |n, i|
+ c[n] = i + 1
+ end
+ out = []
+ a.each do |v|
+ out.push(c[v])
+ end
+ out
+end