aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Bell_West <roger@firedrake.org>2025-02-04 10:50:37 +0000
committerRoger Bell_West <roger@firedrake.org>2025-02-04 10:50:37 +0000
commit4be972678a3d2e97cc72b496d0c21424555efe1e (patch)
tree8632a534b7a5620a5b22c404d25fd34490373014
parentaaab417272f7ae13ade34c68a033d2b1214886d3 (diff)
downloadperlweeklychallenge-club-4be972678a3d2e97cc72b496d0c21424555efe1e.tar.gz
perlweeklychallenge-club-4be972678a3d2e97cc72b496d0c21424555efe1e.tar.bz2
perlweeklychallenge-club-4be972678a3d2e97cc72b496d0c21424555efe1e.zip
RogerBW solutions for challenge no. 307
-rwxr-xr-xchallenge-307/roger-bell-west/crystal/ch-1.cr25
-rwxr-xr-xchallenge-307/roger-bell-west/crystal/ch-2.cr22
-rwxr-xr-xchallenge-307/roger-bell-west/javascript/ch-1.js63
-rwxr-xr-xchallenge-307/roger-bell-west/javascript/ch-2.js32
-rw-r--r--challenge-307/roger-bell-west/kotlin/ch-1.kt33
-rw-r--r--challenge-307/roger-bell-west/kotlin/ch-2.kt30
-rwxr-xr-xchallenge-307/roger-bell-west/lua/ch-1.lua64
-rwxr-xr-xchallenge-307/roger-bell-west/lua/ch-2.lua51
-rwxr-xr-xchallenge-307/roger-bell-west/perl/ch-1.pl22
-rwxr-xr-xchallenge-307/roger-bell-west/perl/ch-2.pl24
-rw-r--r--challenge-307/roger-bell-west/postscript/ch-1.ps254
-rw-r--r--challenge-307/roger-bell-west/postscript/ch-2.ps246
-rwxr-xr-xchallenge-307/roger-bell-west/python/ch-1.py25
-rwxr-xr-xchallenge-307/roger-bell-west/python/ch-2.py21
-rwxr-xr-xchallenge-307/roger-bell-west/raku/ch-1.p620
-rwxr-xr-xchallenge-307/roger-bell-west/raku/ch-2.p622
-rwxr-xr-xchallenge-307/roger-bell-west/ruby/ch-1.rb30
-rwxr-xr-xchallenge-307/roger-bell-west/ruby/ch-2.rb26
-rwxr-xr-xchallenge-307/roger-bell-west/rust/ch-1.rs27
-rwxr-xr-xchallenge-307/roger-bell-west/rust/ch-2.rs28
-rw-r--r--challenge-307/roger-bell-west/scala/ch-1.scala35
-rw-r--r--challenge-307/roger-bell-west/scala/ch-2.scala32
-rw-r--r--challenge-307/roger-bell-west/tests.json28
23 files changed, 1160 insertions, 0 deletions
diff --git a/challenge-307/roger-bell-west/crystal/ch-1.cr b/challenge-307/roger-bell-west/crystal/ch-1.cr
new file mode 100755
index 0000000000..b1553bf54a
--- /dev/null
+++ b/challenge-307/roger-bell-west/crystal/ch-1.cr
@@ -0,0 +1,25 @@
+#! /usr/bin/crystal
+
+def checkorder(a)
+ b = a.sort
+ out = Array(Int32).new
+ a.each_with_index do |c, i|
+ if b[i] != c
+ out.push(i)
+ end
+ end
+ out
+end
+
+require "spec"
+describe "checkorder" do
+ it "test_ex1" do
+ checkorder([5, 2, 4, 3, 1]).should eq [0, 2, 3, 4]
+ end
+ it "test_ex2" do
+ checkorder([1, 2, 1, 1, 3]).should eq [1, 3]
+ end
+ it "test_ex3" do
+ checkorder([3, 1, 3, 2, 3]).should eq [0, 1, 3]
+ end
+end
diff --git a/challenge-307/roger-bell-west/crystal/ch-2.cr b/challenge-307/roger-bell-west/crystal/ch-2.cr
new file mode 100755
index 0000000000..baa71ac565
--- /dev/null
+++ b/challenge-307/roger-bell-west/crystal/ch-2.cr
@@ -0,0 +1,22 @@
+#! /usr/bin/crystal
+
+def findanagrams(a)
+ b = a.map{|x| x.chars.sort.join}
+ out = 1
+ b.each_cons(2) do |s|
+ if s[0] != s[1]
+ out += 1
+ end
+ end
+ out
+end
+
+require "spec"
+describe "findanagrams" do
+ it "test_ex1" do
+ findanagrams(["acca", "dog", "god", "perl", "repl"]).should eq 3
+ end
+ it "test_ex2" do
+ findanagrams(["abba", "baba", "aabb", "ab", "ab"]).should eq 2
+ end
+end
diff --git a/challenge-307/roger-bell-west/javascript/ch-1.js b/challenge-307/roger-bell-west/javascript/ch-1.js
new file mode 100755
index 0000000000..67fb61adee
--- /dev/null
+++ b/challenge-307/roger-bell-west/javascript/ch-1.js
@@ -0,0 +1,63 @@
+#! /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 checkorder(a) {
+ let b = [...a];
+ b.sort(function(a,b) {
+ return a-b;
+ });
+ let out = [];
+ for (let i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ out.push(i);
+ }
+ }
+ return out;
+}
+
+if (deepEqual(checkorder([5, 2, 4, 3, 1]), [0, 2, 3, 4])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(checkorder([1, 2, 1, 1, 3]), [1, 3])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(checkorder([3, 1, 3, 2, 3]), [0, 1, 3])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-307/roger-bell-west/javascript/ch-2.js b/challenge-307/roger-bell-west/javascript/ch-2.js
new file mode 100755
index 0000000000..e3afbdbd96
--- /dev/null
+++ b/challenge-307/roger-bell-west/javascript/ch-2.js
@@ -0,0 +1,32 @@
+#! /usr/bin/node
+
+"use strict"
+
+function findanagrams(a) {
+ let b = [];
+ for (let s of a) {
+ let c = s.split("");
+ c.sort();
+ b.push(c.join(""));
+ }
+ let out = 1;
+ for (let i = 1; i < b.length; i++) {
+ if (b[i - 1] != b[i]) {
+ out += 1;
+ }
+ }
+ return out;
+}
+
+if (findanagrams(['acca', 'dog', 'god', 'perl', 'repl']) == 3) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (findanagrams(['abba', 'baba', 'aabb', 'ab', 'ab']) == 2) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-307/roger-bell-west/kotlin/ch-1.kt b/challenge-307/roger-bell-west/kotlin/ch-1.kt
new file mode 100644
index 0000000000..7a378aa251
--- /dev/null
+++ b/challenge-307/roger-bell-west/kotlin/ch-1.kt
@@ -0,0 +1,33 @@
+fun checkorder(a: List<Int>): List<Int> {
+ var b = a.sorted()
+ var out = ArrayList<Int>()
+ a.forEachIndexed{i, c ->
+ if (b[i] != c) {
+ out.add(i)
+ }
+ }
+ return out.toList()
+}
+
+fun main() {
+
+ if (checkorder(listOf(5, 2, 4, 3, 1)) == listOf(0, 2, 3, 4)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (checkorder(listOf(1, 2, 1, 1, 3)) == listOf(1, 3)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (checkorder(listOf(3, 1, 3, 2, 3)) == listOf(0, 1, 3)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-307/roger-bell-west/kotlin/ch-2.kt b/challenge-307/roger-bell-west/kotlin/ch-2.kt
new file mode 100644
index 0000000000..97178d031b
--- /dev/null
+++ b/challenge-307/roger-bell-west/kotlin/ch-2.kt
@@ -0,0 +1,30 @@
+fun findanagrams(a: List<String>): Int {
+ var b = ArrayList<String>()
+ for (s in a) {
+ b.add(s.toList().sorted().joinToString(""))
+ }
+ var out = 1
+ for (s in b.windowed(size = 2)) {
+ if (s[0] != s[1]) {
+ out += 1
+ }
+ }
+ return out
+}
+
+fun main() {
+
+ if (findanagrams(listOf("acca", "dog", "god", "perl", "repl")) == 3) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (findanagrams(listOf("abba", "baba", "aabb", "ab", "ab")) == 2) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-307/roger-bell-west/lua/ch-1.lua b/challenge-307/roger-bell-west/lua/ch-1.lua
new file mode 100755
index 0000000000..69a8f1f295
--- /dev/null
+++ b/challenge-307/roger-bell-west/lua/ch-1.lua
@@ -0,0 +1,64 @@
+#! /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 checkorder(a)
+ local b = a
+ table.sort(b, function (i, j) return i < j end)
+ local out = {}
+ for i = 1, #a do
+ if a[i] ~= b[i] then
+ table.insert(out, i)
+ end
+ end
+ return out
+end
+
+if recursive_compare(checkorder({5, 2, 4, 3, 1}), {0, 2, 3, 4}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(checkorder({1, 2, 1, 1, 3}), {1, 3}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(checkorder({3, 1, 3, 2, 3}), {0, 1, 3}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-307/roger-bell-west/lua/ch-2.lua b/challenge-307/roger-bell-west/lua/ch-2.lua
new file mode 100755
index 0000000000..5e0f75eb2d
--- /dev/null
+++ b/challenge-307/roger-bell-west/lua/ch-2.lua
@@ -0,0 +1,51 @@
+#! /usr/bin/lua
+
+function split(t)
+ local cl = {}
+ string.gsub(t,
+ "(.)",
+ function(c)
+ table.insert(cl, c)
+ end
+ )
+ return cl
+end
+
+function join(t)
+ local out=""
+ for i, v in ipairs(t) do
+ out = out .. v
+ end
+ return out
+end
+
+function findanagrams(a)
+ local b = {}
+ for _, s in ipairs(a) do
+ c = split(s)
+ table.sort(c)
+ table.insert(b, join(c))
+ end
+ local out = 1
+ for i = 2, #a do
+ if b[i - 1] ~= b[i] then
+ out = out + 1
+ end
+ end
+ return out
+end
+
+if findanagrams({"acca", "dog", "god", "perl", "repl"}) == 3 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if findanagrams({"abba", "baba", "aabb", "ab", "ab"}) == 2 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-307/roger-bell-west/perl/ch-1.pl b/challenge-307/roger-bell-west/perl/ch-1.pl
new file mode 100755
index 0000000000..7859357ffe
--- /dev/null
+++ b/challenge-307/roger-bell-west/perl/ch-1.pl
@@ -0,0 +1,22 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 3;
+
+is_deeply(checkorder([5, 2, 4, 3, 1]), [0, 2, 3, 4], 'example 1');
+is_deeply(checkorder([1, 2, 1, 1, 3]), [1, 3], 'example 2');
+is_deeply(checkorder([3, 1, 3, 2, 3]), [0, 1, 3], 'example 3');
+
+sub checkorder($a) {
+ my @b = sort {$::a <=> $::b} @{$a};
+ my @out;
+ foreach my $i (0 .. $#b) {
+ if ($a->[$i] != $b[$i]) {
+ push @out, $i;
+ }
+ }
+ \@out;
+}
diff --git a/challenge-307/roger-bell-west/perl/ch-2.pl b/challenge-307/roger-bell-west/perl/ch-2.pl
new file mode 100755
index 0000000000..219c8d6653
--- /dev/null
+++ b/challenge-307/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 => 2;
+
+is(findanagrams(['acca', 'dog', 'god', 'perl', 'repl']), 3, 'example 1');
+is(findanagrams(['abba', 'baba', 'aabb', 'ab', 'ab']), 2, 'example 2');
+
+sub findanagrams($a) {
+ my @b;
+ foreach my $s (@{$a}) {
+ push @b, join("", sort split("", $s));
+ }
+ my $out = 1;
+ foreach my $i (1 .. $#b) {
+ if ($b[$i - 1] ne $b[$i]) {
+ $out++;
+ }
+ }
+ $out;
+}
diff --git a/challenge-307/roger-bell-west/postscript/ch-1.ps b/challenge-307/roger-bell-west/postscript/ch-1.ps
new file mode 100644
index 0000000000..152e34793f
--- /dev/null
+++ b/challenge-307/roger-bell-west/postscript/ch-1.ps
@@ -0,0 +1,254 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/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
+
+/keys { % dict -> array of dict keys
+ [ exch
+ {
+ pop
+ } forall
+ ]
+} 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
+
+/deepcopy {
+ 2 dict begin
+ /a exch def
+ a type /dicttype eq {
+ <<
+ a keys {
+ /k exch def
+ k
+ a k get deepcopy
+ } forall
+ >>
+ } {
+ a type /arraytype eq {
+ [
+ a {
+ deepcopy
+ } forall
+ ]
+ } {
+ a type /stringtype eq {
+ a dup length string cvs
+ } {
+ a
+ } ifelse
+ } ifelse
+ } ifelse
+ end
+} bind def
+
+/test.start {
+ print (:) print
+ /test.pass 0 def
+ /test.count 0 def
+} 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 {
+ { quicksort.cmp } quicksort.with_comparator
+} 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
+
+/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
+
+/quicksort.cmp {
+ 2 copy
+ lt {
+ pop pop -1
+ } {
+ gt {
+ 1
+ } {
+ 0
+ } ifelse
+ } ifelse
+} 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
+
+/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.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
+
+
+% end included library code
+
+/checkorder {
+ 0 dict begin
+ /a exch def
+ /b a deepcopy quicksort def
+ [
+ a enumerate.array {
+ aload pop
+ /c exch def
+ /i exch def
+ b i get c ne {
+ i
+ } if
+ } forall
+ ]
+ end
+} bind def
+
+(checkorder) test.start
+[5 2 4 3 1] checkorder [0 2 3 4] deepeq test
+[1 2 1 1 3] checkorder [1 3] deepeq test
+[3 1 3 2 3] checkorder [0 1 3] deepeq test
+test.end
diff --git a/challenge-307/roger-bell-west/postscript/ch-2.ps b/challenge-307/roger-bell-west/postscript/ch-2.ps
new file mode 100644
index 0000000000..e15ddd1a86
--- /dev/null
+++ b/challenge-307/roger-bell-west/postscript/ch-2.ps
@@ -0,0 +1,246 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/rotor {
+ 5 dict begin
+ /delta exch def
+ /size exch def
+ dup length /len exch def
+ /ar exch def
+ /ix 0 def
+ [
+ {
+ ix size add len gt {
+ exit
+ } if
+ ar ix size getinterval
+ /ix ix size delta add add def
+ } loop
+ ]
+ end
+} bind def
+
+/quicksort.cmp {
+ 2 copy
+ lt {
+ pop pop -1
+ } {
+ gt {
+ 1
+ } {
+ 0
+ } ifelse
+ } ifelse
+} 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
+
+/s2a {
+ [ exch { } forall ]
+} 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
+
+/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
+
+/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
+
+/map { % array proc -> array
+ 2 dict begin
+ /p exch def
+ [ exch
+ {
+ p
+ } forall
+ ]
+ end
+} bind def
+
+/quicksort {
+ { quicksort.cmp } quicksort.with_comparator
+} 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
+
+/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
+
+/test.start {
+ print (:) print
+ /test.pass 0 def
+ /test.count 0 def
+} bind def
+
+
+% end included library code
+
+/findanagrams {
+ 1 exch
+ {
+ s2a quicksort a2s
+ } map
+ 2 -1 rotor
+ {
+ aload pop deepeq not {
+ 1 add
+ } if
+ } forall
+} bind def
+
+(findanagrams) test.start
+[(acca) (dog) (god) (perl) (repl)] findanagrams 3 eq test
+[(abba) (baba) (aabb) (ab) (ab)] findanagrams 2 eq test
+test.end
diff --git a/challenge-307/roger-bell-west/python/ch-1.py b/challenge-307/roger-bell-west/python/ch-1.py
new file mode 100755
index 0000000000..82416a2927
--- /dev/null
+++ b/challenge-307/roger-bell-west/python/ch-1.py
@@ -0,0 +1,25 @@
+#! /usr/bin/python3
+
+def checkorder(a):
+ b = a.copy()
+ b.sort()
+ out = []
+ for i, c in enumerate(a):
+ if b[i] != c:
+ out.append(i)
+ return out
+
+import unittest
+
+class TestCheckorder(unittest.TestCase):
+
+ def test_ex1(self):
+ self.assertEqual(checkorder([5, 2, 4, 3, 1]), [0, 2, 3, 4], 'example 1')
+
+ def test_ex2(self):
+ self.assertEqual(checkorder([1, 2, 1, 1, 3]), [1, 3], 'example 2')
+
+ def test_ex3(self):
+ self.assertEqual(checkorder([3, 1, 3, 2, 3]), [0, 1, 3], 'example 3')
+
+unittest.main()
diff --git a/challenge-307/roger-bell-west/python/ch-2.py b/challenge-307/roger-bell-west/python/ch-2.py
new file mode 100755
index 0000000000..155ecdbd29
--- /dev/null
+++ b/challenge-307/roger-bell-west/python/ch-2.py
@@ -0,0 +1,21 @@
+#! /usr/bin/python3
+
+def findanagrams(a):
+ b = ["".join(sorted(s)) for s in a]
+ out = 1
+ for i in range(1, len(b)):
+ if b[i - 1] != b[i]:
+ out += 1
+ return out
+
+import unittest
+
+class TestFindanagrams(unittest.TestCase):
+
+ def test_ex1(self):
+ self.assertEqual(findanagrams(["acca", "dog", "god", "perl", "repl"]), 3, 'example 1')
+
+ def test_ex2(self):
+ self.assertEqual(findanagrams(["abba", "baba", "aabb", "ab", "ab"]), 2, 'example 2')
+
+unittest.main()
diff --git a/challenge-307/roger-bell-west/raku/ch-1.p6 b/challenge-307/roger-bell-west/raku/ch-1.p6
new file mode 100755
index 0000000000..abd01dc5ec
--- /dev/null
+++ b/challenge-307/roger-bell-west/raku/ch-1.p6
@@ -0,0 +1,20 @@
+#! /usr/bin/raku
+
+use Test;
+
+plan 3;
+
+is-deeply(checkorder([5, 2, 4, 3, 1]), [0, 2, 3, 4], 'example 1');
+is-deeply(checkorder([1, 2, 1, 1, 3]), [1, 3], 'example 2');
+is-deeply(checkorder([3, 1, 3, 2, 3]), [0, 1, 3], 'example 3');
+
+sub checkorder(@a) {
+ my @b = @a.sort({$^a <=> $^b});
+ my @out;
+ for @b.kv -> $i, $c {
+ if (@a[$i] != $c) {
+ @out.push($i);
+ }
+ }
+ @out;
+}
diff --git a/challenge-307/roger-bell-west/raku/ch-2.p6 b/challenge-307/roger-bell-west/raku/ch-2.p6
new file mode 100755
index 0000000000..513a3c30e1
--- /dev/null
+++ b/challenge-307/roger-bell-west/raku/ch-2.p6
@@ -0,0 +1,22 @@
+#! /usr/bin/raku
+
+use Test;
+
+plan 2;
+
+is(findanagrams(['acca', 'dog', 'god', 'perl', 'repl']), 3, 'example 1');
+is(findanagrams(['abba', 'baba', 'aabb', 'ab', 'ab']), 2, 'example 2');
+
+sub findanagrams(@a) {
+ my @b;
+ for @a -> $s {
+ @b.push($s.comb.sort.join(""));
+ }
+ my $out = 1;
+ for 1 .. @b.end -> $i {
+ if (@b[$i - 1] ne @b[$i]) {
+ $out++;
+ }