aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2025-01-21 12:02:30 +0000
committerGitHub <noreply@github.com>2025-01-21 12:02:30 +0000
commitef6299c2c9becccf7164d42468ed3112f613f9c7 (patch)
treecf31000c115a647f3bb910557daca80560d5667b
parentcd133c017b38bc71d46d2cd0f612deabe680acb6 (diff)
parentf8752958679af48261bd42f9c2457217bcec9e81 (diff)
downloadperlweeklychallenge-club-ef6299c2c9becccf7164d42468ed3112f613f9c7.tar.gz
perlweeklychallenge-club-ef6299c2c9becccf7164d42468ed3112f613f9c7.tar.bz2
perlweeklychallenge-club-ef6299c2c9becccf7164d42468ed3112f613f9c7.zip
Merge pull request #11477 from Firedrake/rogerbw-challenge-305
RogerBW solutions for challenge no. 305
-rwxr-xr-xchallenge-305/roger-bell-west/crystal/ch-1.cr66
-rwxr-xr-xchallenge-305/roger-bell-west/crystal/ch-2.cr36
-rwxr-xr-xchallenge-305/roger-bell-west/javascript/ch-1.js89
-rwxr-xr-xchallenge-305/roger-bell-west/javascript/ch-2.js74
-rw-r--r--challenge-305/roger-bell-west/kotlin/ch-1.kt76
-rw-r--r--challenge-305/roger-bell-west/kotlin/ch-2.kt48
-rwxr-xr-xchallenge-305/roger-bell-west/lua/ch-1.lua92
-rwxr-xr-xchallenge-305/roger-bell-west/lua/ch-2.lua86
-rwxr-xr-xchallenge-305/roger-bell-west/perl/ch-1.pl26
-rwxr-xr-xchallenge-305/roger-bell-west/perl/ch-2.pl35
-rw-r--r--challenge-305/roger-bell-west/postscript/ch-1.ps183
-rw-r--r--challenge-305/roger-bell-west/postscript/ch-2.ps318
-rwxr-xr-xchallenge-305/roger-bell-west/python/ch-1.py57
-rwxr-xr-xchallenge-305/roger-bell-west/python/ch-2.py30
-rwxr-xr-xchallenge-305/roger-bell-west/raku/ch-1.p651
-rwxr-xr-xchallenge-305/roger-bell-west/raku/ch-2.p631
-rwxr-xr-xchallenge-305/roger-bell-west/ruby/ch-1.rb34
-rwxr-xr-xchallenge-305/roger-bell-west/ruby/ch-2.rb40
-rwxr-xr-xchallenge-305/roger-bell-west/rust/ch-1.rs70
-rwxr-xr-xchallenge-305/roger-bell-west/rust/ch-2.rs37
-rw-r--r--challenge-305/roger-bell-west/scala/ch-1.scala80
-rw-r--r--challenge-305/roger-bell-west/scala/ch-2.scala41
-rw-r--r--challenge-305/roger-bell-west/tests.json36
23 files changed, 1636 insertions, 0 deletions
diff --git a/challenge-305/roger-bell-west/crystal/ch-1.cr b/challenge-305/roger-bell-west/crystal/ch-1.cr
new file mode 100755
index 0000000000..67645dd0e7
--- /dev/null
+++ b/challenge-305/roger-bell-west/crystal/ch-1.cr
@@ -0,0 +1,66 @@
+#! /usr/bin/crystal
+
+def isqrt(s)
+ if s <= 1
+ return s
+ end
+ x0 = s / 2;
+ x1 = (x0 + s / x0) / 2;
+ while x1 < x0
+ x0 = x1
+ x1 = (x0 + s / x0) / 2
+ end
+ x0
+end
+
+def is_prime(n)
+ if n == 1
+ return false
+ end
+ if n>2 && n%2==0
+ return false
+ end
+ if n>3 && n%3==0
+ return false
+ end
+ lim = isqrt(n)
+ k6 = 0;
+ while true
+ k6 += 6
+ (k6 - 1).step(to: k6 + 1, by: 2) do |t|
+ if t <= lim
+ if n % t == 0
+ return false
+ end
+ else
+ return true
+ end
+ end
+ end
+end
+
+def binaryprefix(a)
+ out = Array(Bool).new
+ n = 0
+ a.each do |x|
+ n *= 2
+ if x == 1
+ n += 1
+ end
+ out.push(is_prime(n))
+ end
+ out
+end
+
+require "spec"
+describe "binaryprefix" do
+ it "test_ex1" do
+ binaryprefix([1, 0, 1]).should eq [false, true, true]
+ end
+ it "test_ex2" do
+ binaryprefix([1, 1, 0]).should eq [false, true, false]
+ end
+ it "test_ex3" do
+ binaryprefix([1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1]).should eq [false, true, true, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, true]
+ end
+end
diff --git a/challenge-305/roger-bell-west/crystal/ch-2.cr b/challenge-305/roger-bell-west/crystal/ch-2.cr
new file mode 100755
index 0000000000..768adccfc3
--- /dev/null
+++ b/challenge-305/roger-bell-west/crystal/ch-2.cr
@@ -0,0 +1,36 @@
+#! /usr/bin/crystal
+
+def aliendictionary(a, dc)
+ mxl = a.map { |x| x.size }.max
+ dh = Hash(Char, Int64).new
+ dc.each_with_index do |c, i|
+ dh[c] = i.to_i64
+ end
+ b = a
+ numerics = Hash(String, Int64).new
+ b.each do |w|
+ n = 0.to_i64
+ cc = w.chars
+ 0.upto(mxl - 1) do |i|
+ n *= 27.to_i64
+ if i < w.size
+ n += dh[cc[i]]
+ end
+ end
+ numerics[w] = n
+ end
+ b.sort! do |i, j|
+ numerics[i] <=> numerics[j]
+ end
+ b
+end
+
+require "spec"
+describe "aliendictionary" do
+ it "test_ex1" do
+ aliendictionary(["perl", "python", "raku"], ['h', 'l', 'a', 'b', 'y', 'd', 'e', 'f', 'g', 'i', 'r', 'k', 'm', 'n', 'o', 'p', 'q', 'j', 's', 't', 'u', 'v', 'w', 'x', 'c', 'z']).should eq ["raku", "python", "perl"]
+ end
+ it "test_ex2" do
+ aliendictionary(["the", "weekly", "challenge"], ['c', 'o', 'r', 'l', 'd', 'a', 'b', 't', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'p', 'q', 's', 'w', 'u', 'v', 'x', 'y', 'z']).should eq ["challenge", "the", "weekly"]
+ end
+end
diff --git a/challenge-305/roger-bell-west/javascript/ch-1.js b/challenge-305/roger-bell-west/javascript/ch-1.js
new file mode 100755
index 0000000000..951d12bf8a
--- /dev/null
+++ b/challenge-305/roger-bell-west/javascript/ch-1.js
@@ -0,0 +1,89 @@
+#! /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 is_prime(candidate) {
+ if (candidate<2) {
+ return false
+ } else if (candidate==2) {
+ return true
+ } else if (candidate==3) {
+ return true
+ } else if (candidate % 2 == 0) {
+ return false
+ } else if (candidate % 3 == 0) {
+ return false
+ }
+ let anchor=0
+ let limit=Math.floor(Math.sqrt(candidate))
+ while (1) {
+ anchor+=6
+ for (let t = anchor-1; t <= anchor+1; t += 2) {
+ if (t > limit) {
+ return true
+ }
+ if (candidate % t == 0) {
+ return false
+ }
+ }
+ }
+}
+
+function binaryprefix(a) {
+ let out = [];
+ let n = 0;
+ for (let x of a) {
+ n *= 2
+ if (x == 1) {
+ n += 1;
+ }
+ out.push(is_prime(n));
+ }
+ return out;
+}
+
+if (deepEqual(binaryprefix([1, 0, 1]), [false, true, true])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(binaryprefix([1, 1, 0]), [false, true, false])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(binaryprefix([1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1]), [false, true, true, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, true])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-305/roger-bell-west/javascript/ch-2.js b/challenge-305/roger-bell-west/javascript/ch-2.js
new file mode 100755
index 0000000000..3b9bf69629
--- /dev/null
+++ b/challenge-305/roger-bell-west/javascript/ch-2.js
@@ -0,0 +1,74 @@
+#! /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 aliendictionary(a, dc) {
+ const mxl = Math.max(...a.map(x => x.length));
+ let dh = new Map;
+ dc.forEach((c, i) => {
+ dh.set(c, i + 1);
+ });
+ let b = [...a];
+ let numerics = new Map;
+ for (let w of a) {
+ let n = 0n;
+ let cc = w.split("");
+ for (let i = 0; i < mxl; i++) {
+ n *= 27n;
+ if (i < w.length) {
+ n += BigInt(dh.get(cc[i]));
+ }
+ }
+ numerics.set(w, n);
+ }
+ b.sort(function(i, j) {
+ const d = numerics.get(i) - numerics.get(j);
+ if (d < 0) {
+ return -1;
+ } else if (d > 0) {
+ return 1;
+ }
+ return 0;
+ });
+ return b;
+}
+
+if (deepEqual(aliendictionary(['perl', 'python', 'raku'], ['h', 'l', 'a', 'b', 'y', 'd', 'e', 'f', 'g', 'i', 'r', 'k', 'm', 'n', 'o', 'p', 'q', 'j', 's', 't', 'u', 'v', 'w', 'x', 'c', 'z']), ['raku', 'python', 'perl'])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(aliendictionary(['the', 'weekly', 'challenge'], ['c', 'o', 'r', 'l', 'd', 'a', 'b', 't', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'p', 'q', 's', 'w', 'u', 'v', 'x', 'y', 'z']), ['challenge', 'the', 'weekly'])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-305/roger-bell-west/kotlin/ch-1.kt b/challenge-305/roger-bell-west/kotlin/ch-1.kt
new file mode 100644
index 0000000000..27e9070714
--- /dev/null
+++ b/challenge-305/roger-bell-west/kotlin/ch-1.kt
@@ -0,0 +1,76 @@
+fun isqrt(s: Int): Int {
+ if (s <= 1) {
+ return s
+ } else {
+ var x0 = s / 2
+ var x1 = (x0 + s / x0) / 2
+ while (x1 < x0) {
+ x0 = x1
+ x1 = (x0 + s / x0) / 2
+ }
+ return x0
+ }
+}
+
+fun is_prime(candidate: Int): Boolean {
+ if (candidate < 2) {
+ return false
+ } else if (candidate==2) {
+ return true
+ } else if (candidate==3) {
+ return true
+ } else if (candidate % 2 == 0) {
+ return false
+ } else if (candidate % 3 == 0) {
+ return false
+ }
+ var anchor=0
+ val limit = isqrt(candidate)
+ while (true) {
+ anchor += 6
+ for (t in anchor-1..anchor+1 step 2) {
+ if (t > limit) {
+ return true
+ }
+ if (candidate % t == 0) {
+ return false
+ }
+ }
+ }
+}
+
+fun binaryprefix(a: List<Int>): List<Boolean> {
+ var out = ArrayList<Boolean>()
+ var n = 0
+ for (x in a) {
+ n *= 2
+ if (x == 1) {
+ n += 1
+ }
+ out.add(is_prime(n))
+ }
+ return out.toList()
+}
+
+fun main() {
+
+ if (binaryprefix(listOf(1, 0, 1)) == listOf(false, true, true)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (binaryprefix(listOf(1, 1, 0)) == listOf(false, true, false)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (binaryprefix(listOf(1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1)) == listOf(false, true, true, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, true)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-305/roger-bell-west/kotlin/ch-2.kt b/challenge-305/roger-bell-west/kotlin/ch-2.kt
new file mode 100644
index 0000000000..d678e4d8e1
--- /dev/null
+++ b/challenge-305/roger-bell-west/kotlin/ch-2.kt
@@ -0,0 +1,48 @@
+fun aliendictionary(a: List<String>, dc: List<Char>): List<String> {
+ val mxl = a.map{it.length}.maxOrNull()!!
+ var dh = mutableMapOf<Char, Int>()
+ dc.forEachIndexed{i, c ->
+ dh.set(c, i + 1)
+ }
+ var numerics = mutableMapOf<String, Long>()
+ for (w in a) {
+ var n = 0.toLong()
+ val cc = w.toList()
+ for (i in 0 .. mxl - 1) {
+ n *= 27.toLong()
+ if (i < w.length) {
+ n += dh.getValue(cc[i]).toLong()
+ }
+ }
+ numerics.set(w, n)
+ }
+ val customComparator = Comparator {
+ i: String, j: String ->
+ val d = numerics.getValue(i) - numerics.getValue(j)
+ if (d > 0L) {
+ 1
+ } else if (d < 0L) {
+ -1
+ } else {
+ 0
+ }
+ }
+ return a.sortedWith(customComparator)
+}
+
+fun main() {
+
+ if (aliendictionary(listOf("perl", "python", "raku"), listOf('h', 'l', 'a', 'b', 'y', 'd', 'e', 'f', 'g', 'i', 'r', 'k', 'm', 'n', 'o', 'p', 'q', 'j', 's', 't', 'u', 'v', 'w', 'x', 'c', 'z')) == listOf("raku", "python", "perl")) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(' ')
+ if (aliendictionary(listOf("the", "weekly", "challenge"), listOf('c', 'o', 'r', 'l', 'd', 'a', 'b', 't', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'p', 'q', 's', 'w', 'u', 'v', 'x', 'y', 'z')) == listOf("challenge", "the", "weekly")) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-305/roger-bell-west/lua/ch-1.lua b/challenge-305/roger-bell-west/lua/ch-1.lua
new file mode 100755
index 0000000000..a5a16f3d93
--- /dev/null
+++ b/challenge-305/roger-bell-west/lua/ch-1.lua
@@ -0,0 +1,92 @@
+#! /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 is_prime(candidate)
+ if candidate<2 then
+ return false
+ elseif candidate==2 then
+ return true
+ elseif candidate==3 then
+ return true
+ elseif candidate % 2 == 0 then
+ return false
+ elseif candidate % 3 == 0 then
+ return false
+ end
+ local anchor=0
+ local limit=math.floor(math.sqrt(candidate))
+ while true do
+ anchor = anchor + 6
+ for t = anchor-1,anchor+1,2 do
+ if t > limit then
+ return true
+ end
+ if candidate % t == 0 then
+ return false
+ end
+ end
+ end
+end
+
+function binaryprefix(a)
+ local out = {}
+ local n = 0
+ for _, x in ipairs(a) do
+ n = n * 2
+ if x == 1 then
+ n = n + 1
+ end
+ table.insert(out, is_prime(n))
+ end
+ return out
+end
+
+if recursive_compare(binaryprefix({1, 0, 1}), {false, true, true}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(binaryprefix({1, 1, 0}), {false, true, false}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(binaryprefix({1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1}), {false, true, true, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, true}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-305/roger-bell-west/lua/ch-2.lua b/challenge-305/roger-bell-west/lua/ch-2.lua
new file mode 100755
index 0000000000..e9974e511a
--- /dev/null
+++ b/challenge-305/roger-bell-west/lua/ch-2.lua
@@ -0,0 +1,86 @@
+#! /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 split(t)
+ local cl = {}
+ string.gsub(t,
+ "(.)",
+ function(c)
+ table.insert(cl, c)
+ end
+ )
+ return cl
+end
+
+function aliendictionary(a, dc)
+ local mxl = 0
+ for _, w in ipairs(a) do
+ mxl = math.max(mxl, #w)
+ end
+ local dh = {}
+ for i, c in ipairs(dc) do
+ dh[c] = i
+ end
+ local b = a
+ local numerics = {}
+ for _, w in ipairs(a) do
+ local n = 0
+ local cc = split(w)
+ for i = 1, mxl do
+ n = n * 27
+ if i <= #w then
+ n = n + dh[cc[i]]
+ end
+ end
+ numerics[w] = n
+ end
+ table.sort(b,
+ function(i, j)
+ return numerics[i] < numerics[j]
+ end
+ )
+ return b
+end
+
+if recursive_compare(aliendictionary({"perl", "python", "raku"}, {"h", "l", "a", "b", "y", "d", "e", "f", "g", "i", "r", "k", "m", "n", "o", "p", "q", "j", "s", "t", "u", "v", "w", "x", "c", "z"}), {"raku", "python", "perl"}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(aliendictionary({"the", "weekly", "challenge"}, {"c", "o", "r", "l", "d", "a", "b", "t", "e", "f", "g", "h", "i", "j", "k", "m", "n", "p", "q", "s", "w", "u", "v", "x", "y", "z"}), {"challenge", "the", "weekly"}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-305/roger-bell-west/perl/ch-1.pl b/challenge-305/roger-bell-west/perl/ch-1.pl
new file mode 100755
index 0000000000..e05413d206
--- /dev/null
+++ b/challenge-305/roger-bell-west/perl/ch-1.pl
@@ -0,0 +1,26 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 3;
+
+is_deeply(binaryprefix([1, 0, 1]), [0, 1, 1], 'example 1');
+is_deeply(binaryprefix([1, 1, 0]), [0, 1, 0], 'example 2');
+is_deeply(binaryprefix([1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1]), [0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 'example 3');
+
+use Math::Prime::Util qw(is_prime);
+
+sub binaryprefix($a) {
+ my @out;
+ my $n = 0;
+ foreach my $x (@{$a}) {
+ $n *= 2;
+ if ($x == 1) {
+ $n++;
+ }
+ push @out, is_prime($n)?1:0;
+ }
+ \@out;
+}
diff --git a/challenge-305/roger-bell-west/perl/ch-2.pl b/challenge-305/roger-bell-west/perl/ch-2.pl
new file mode 100755
index 0000000000..ba5b1724b4
--- /dev/null
+++ b/challenge-305/roger-bell-west/perl/ch-2.pl
@@ -0,0 +1,35 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 2;
+
+is_deeply(aliendictionary(['perl', 'python', 'raku'], ['h', 'l', 'a', 'b', 'y', 'd', 'e', 'f', 'g', 'i', 'r', 'k', 'm', 'n', 'o', 'p', 'q', 'j', 's', 't', 'u', 'v', 'w', 'x', 'c', 'z']), ['raku', 'python', 'perl'], 'example 1');
+is_deeply(aliendictionary(['the', 'weekly', 'challenge'], ['c', 'o', 'r', 'l', 'd', 'a', 'b', 't', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'p', 'q', 's', 'w', 'u', 'v', 'x', 'y', 'z']), ['challenge', 'the', 'weekly'], 'example 2');
+
+use List::Util qw(max);
+
+sub aliendictionary($a, $dc) {
+ my $mxl = max(map {length($_)} @{$a});
+ my %dh;
+ while (my ($i, $c) = each @{$dc}) {
+ $dh{$c} = $i + 1;
+ }
+ my @b = @{$a};
+ my %numerics;
+ foreach my $w (@b) {
+ my $n = 0;
+ my @cc = split '', $w;
+ foreach my $i (0 .. $mxl - 1) {
+ $n *= 27;
+ if ($i < length($w)) {
+ $n += $dh{$cc[$i]};
+ }
+ }
+ $numerics{$w} = $n;
+ }
+ @b = sort { $numerics{$::a} <=> $numerics{$::b} } @b;
+ return \@b;
+}
diff --git a/challenge-305/roger-bell-west/postscript/ch-1.ps b/challenge-305/roger-bell-west/postscript/ch-1.ps
new file mode 100644
index 0000000000..4515cf8337
--- /dev/null
+++ b/challenge-305/roger-bell-west/postscript/ch-1.ps
@@ -0,0 +1,183 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/isqrt {
+ 0 dict begin
+ /s exch def
+ s 1 le {
+ s
+ } {
+ /x0 s 2 idiv def
+ /x1 x0 s x0 idiv add 2 idiv def
+ {
+ x1 x0 ge {
+ exit
+ } if
+ /x0 x1 def
+ /x1 x0 s x0 idiv add 2 idiv def
+ } loop
+ x0
+ } ifelse
+ 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
+
+/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
+
+/isprime {
+ 4 dict begin
+ /candidate exch def
+ 1 {
+ candidate 2 lt {
+ false
+ exit
+ } if
+ candidate 2 eq {
+ true
+ exit
+ } if
+ candidate 2 mod 0 eq {
+ false
+ exit
+ } if
+ candidate 3 eq {
+ true
+ exit
+ } if
+ candidate 3 mod 0 eq {
+ false
+ exit
+ } if
+ /prime true def
+ /limit candidate isqrt 1 add def
+ /anchor 0 def
+ {
+ /anchor anchor 6 add def
+ anchor limit gt {
+ exit
+ } if
+ [ -1 1 ] {
+ anchor add candidate exch mod 0 eq {
+ /prime false def
+ exit
+ } if
+ } forall
+ prime false eq {
+ exit
+ } if
+ } loop
+ prime
+ } repeat
+ end
+} bind def
+
+
+% end included library code
+
+/binaryprefix {
+ 0 dict begin
+ [ exch
+ /n 0 def
+ {
+ /n n 2 mul def
+ 1 eq {
+ /n n 1 add def
+ } if
+ n isprime
+ } forall
+ ]
+ end
+} bind def
+
+(binaryprefix) test.start
+[1 0 1] binaryprefix [false true true] deepeq test
+[1 1 0] binaryprefix [false true false] deepeq test
+[1 1 1 1 0 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1] binaryprefix [false true true false false true false false false false false false false false false false false false false true] deepeq test
+test.end
diff --git a/challenge-305/roger-bell-west/postscript/ch-2.ps b/challenge-305/roger-bell-west/postscript/ch-2.ps
new file mode 100644
index 0000000000..68f1a70cc2
--- /dev/null
+++ b/challenge-305/roger-bell-west/postscript/ch-2.ps
@@ -0,0 +1,318 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/map { % array proc -> array
+ 2 dict begin
+ /p exch def
+ [ exch
+ {
+ p
+ } forall
+ ]
+ 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
+
+/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
+
+/listmax {
+ { max } reduce
+} 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
+