aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-321/pokgopun/go/ch-1.go91
-rw-r--r--challenge-321/pokgopun/go/ch-2.go95
-rw-r--r--challenge-321/pokgopun/python/ch-1.py71
-rw-r--r--challenge-321/pokgopun/python/ch-2.py74
-rwxr-xr-xchallenge-321/roger-bell-west/crystal/ch-1.cr24
-rwxr-xr-xchallenge-321/roger-bell-west/crystal/ch-2.cr30
-rwxr-xr-xchallenge-321/roger-bell-west/javascript/ch-1.js36
-rwxr-xr-xchallenge-321/roger-bell-west/javascript/ch-2.js38
-rw-r--r--challenge-321/roger-bell-west/kotlin/ch-1.kt33
-rw-r--r--challenge-321/roger-bell-west/kotlin/ch-2.kt38
-rwxr-xr-xchallenge-321/roger-bell-west/lua/ch-1.lua42
-rwxr-xr-xchallenge-321/roger-bell-west/lua/ch-2.lua58
-rwxr-xr-xchallenge-321/roger-bell-west/perl/ch-1.pl21
-rwxr-xr-xchallenge-321/roger-bell-west/perl/ch-2.pl27
-rw-r--r--challenge-321/roger-bell-west/postscript/ch-1.ps153
-rw-r--r--challenge-321/roger-bell-west/postscript/ch-2.ps120
-rwxr-xr-xchallenge-321/roger-bell-west/python/ch-1.py25
-rwxr-xr-xchallenge-321/roger-bell-west/python/ch-2.py28
-rwxr-xr-xchallenge-321/roger-bell-west/raku/ch-1.p619
-rwxr-xr-xchallenge-321/roger-bell-west/raku/ch-2.p625
-rwxr-xr-xchallenge-321/roger-bell-west/ruby/ch-1.rb31
-rwxr-xr-xchallenge-321/roger-bell-west/ruby/ch-2.rb35
-rwxr-xr-xchallenge-321/roger-bell-west/rust/ch-1.rs30
-rwxr-xr-xchallenge-321/roger-bell-west/rust/ch-2.rs33
-rw-r--r--challenge-321/roger-bell-west/scala/ch-1.scala35
-rw-r--r--challenge-321/roger-bell-west/scala/ch-2.scala40
-rw-r--r--challenge-321/roger-bell-west/tests.json44
-rw-r--r--challenge-321/roger-bell-west/typst/ch-1.typ27
-rw-r--r--challenge-321/roger-bell-west/typst/ch-2.typ33
29 files changed, 1356 insertions, 0 deletions
diff --git a/challenge-321/pokgopun/go/ch-1.go b/challenge-321/pokgopun/go/ch-1.go
new file mode 100644
index 0000000000..baffd55378
--- /dev/null
+++ b/challenge-321/pokgopun/go/ch-1.go
@@ -0,0 +1,91 @@
+//# https://theweeklychallenge.org/blog/perl-weekly-challenge-321/
+/*#
+
+Task 1: Distinct Average
+
+Submitted by: [44]Mohammad Sajid Anwar
+ __________________________________________________________________
+
+ You are given an array of numbers with even length.
+
+ Write a script to return the count of distinct average. The average is
+ calculate by removing the minimum and the maximum, then average of the
+ two.
+
+Example 1
+
+Input: @nums = (1, 2, 4, 3, 5, 6)
+Output: 1
+
+Step 1: Min = 1, Max = 6, Avg = 3.5
+Step 2: Min = 2, Max = 5, Avg = 3.5
+Step 3: Min = 3, Max = 4, Avg = 3.5
+
+The count of distinct average is 1.
+
+Example 2
+
+Input: @nums = (0, 2, 4, 8, 3, 5)
+Output: 2
+
+Step 1: Min = 0, Max = 8, Avg = 4
+Step 2: Min = 2, Max = 5, Avg = 3.5
+Step 3: Min = 3, Max = 4, Avg = 3.5
+
+The count of distinct average is 2.
+
+Example 3
+
+Input: @nums = (7, 3, 1, 0, 5, 9)
+Output: 2
+
+Step 1: Min = 0, Max = 9, Avg = 4.5
+Step 2: Min = 1, Max = 7, Avg = 4
+Step 3: Min = 3, Max = 5, Avg = 4
+
+The count of distinct average is 2.
+
+Task 2: Backspace Compare
+#*/
+//# solution by pokgopun@gmail.com
+
+package main
+
+import (
+ "io"
+ "os"
+ "slices"
+
+ "github.com/google/go-cmp/cmp"
+)
+
+type qr struct {
+ q, r int
+}
+
+type input []int
+
+func (in input) process() int {
+ l := len(in)
+ slices.Sort(in)
+ m := make(map[qr]bool)
+ for i := range l / 2 {
+ sm := (in[i] + in[l-1-i])
+ m[qr{sm / 2, sm % 2}] = true
+ }
+ //fmt.Println(in, m)
+ return len(m)
+}
+
+func main() {
+ for _, data := range []struct {
+ input input
+ output int
+ }{
+ {input{1, 2, 4, 3, 5, 6}, 1},
+ {input{0, 2, 4, 8, 3, 5}, 2},
+ {input{7, 3, 1, 0, 5, 9}, 2},
+ } {
+ io.WriteString(os.Stdout, cmp.Diff(data.input.process(), data.output)) // blank if ok, otherwise show the difference
+ }
+}
diff --git a/challenge-321/pokgopun/go/ch-2.go b/challenge-321/pokgopun/go/ch-2.go
new file mode 100644
index 0000000000..9ea092effd
--- /dev/null
+++ b/challenge-321/pokgopun/go/ch-2.go
@@ -0,0 +1,95 @@
+//# https://theweeklychallenge.org/blog/perl-weekly-challenge-321/
+/*#
+
+Task 2: Backspace Compare
+
+Submitted by: [45]Mohammad Sajid Anwar
+ __________________________________________________________________
+
+ You are given two strings containing zero or more #.
+
+ Write a script to return true if the two given strings are same by
+ treating # as backspace.
+
+Example 1
+
+Input: $str1 = "ab#c"
+ $str2 = "ad#c"
+Output: true
+
+For first string, we remove "b" as it is followed by "#".
+For second string, we remove "d" as it is followed by "#".
+In the end both strings became the same.
+
+Example 2
+
+Input: $str1 = "ab##"
+ $str2 = "a#b#"
+Output: true
+
+Example 3
+
+Input: $str1 = "a#b"
+ $str2 = "c"
+Output: false
+ __________________________________________________________________
+
+ Last date to submit the solution 23:59 (UK Time) Sunday 18th May 2025.
+ __________________________________________________________________
+
+SO WHAT DO YOU THINK ?
+#*/
+//# solution by pokgopun@gmail.com
+
+package main
+
+import (
+ "io"
+ "os"
+ "slices"
+
+ "github.com/google/go-cmp/cmp"
+)
+
+type input struct {
+ str1, str2 string
+}
+
+func (in input) process() bool {
+ //fmt.Printf("%v, '%s', '%s'\n", in, ab(in.str1), ab(in.str2))
+ return ab(in.str1) == ab(in.str2)
+}
+
+func ab(str string) string {
+ l := len(str)
+ bs := []byte(str)
+ i := 0
+ for i < l {
+ if bs[i] == byte('#') {
+ if i > 0 {
+ slices.Delete(bs, i-1, i+1)
+ l -= 2
+ i--
+ } else {
+ slices.Delete(bs, i, i+1)
+ l--
+ }
+ } else {
+ i++
+ }
+ }
+ return string(bs)
+}
+
+func main() {
+ for _, data := range []struct {
+ input input
+ output bool
+ }{
+ {input{"ab#c", "ad#c"}, true},
+ {input{"ab##", "a#b#"}, true},
+ {input{"a#b", "c"}, false},
+ } {
+ io.WriteString(os.Stdout, cmp.Diff(data.input.process(), data.output)) // blank if ok, otherwise show the difference
+ }
+}
diff --git a/challenge-321/pokgopun/python/ch-1.py b/challenge-321/pokgopun/python/ch-1.py
new file mode 100644
index 0000000000..d5ccc2fe7d
--- /dev/null
+++ b/challenge-321/pokgopun/python/ch-1.py
@@ -0,0 +1,71 @@
+### https://theweeklychallenge.org/blog/perl-weekly-challenge-321/
+"""
+
+Task 1: Distinct Average
+
+Submitted by: [44]Mohammad Sajid Anwar
+ __________________________________________________________________
+
+ You are given an array of numbers with even length.
+
+ Write a script to return the count of distinct average. The average is
+ calculate by removing the minimum and the maximum, then average of the
+ two.
+
+Example 1
+
+Input: @nums = (1, 2, 4, 3, 5, 6)
+Output: 1
+
+Step 1: Min = 1, Max = 6, Avg = 3.5
+Step 2: Min = 2, Max = 5, Avg = 3.5
+Step 3: Min = 3, Max = 4, Avg = 3.5
+
+The count of distinct average is 1.
+
+Example 2
+
+Input: @nums = (0, 2, 4, 8, 3, 5)
+Output: 2
+
+Step 1: Min = 0, Max = 8, Avg = 4
+Step 2: Min = 2, Max = 5, Avg = 3.5
+Step 3: Min = 3, Max = 4, Avg = 3.5
+
+The count of distinct average is 2.
+
+Example 3
+
+Input: @nums = (7, 3, 1, 0, 5, 9)
+Output: 2
+
+Step 1: Min = 0, Max = 9, Avg = 4.5
+Step 2: Min = 1, Max = 7, Avg = 4
+Step 3: Min = 3, Max = 5, Avg = 4
+
+The count of distinct average is 2.
+
+Task 2: Backspace Compare
+"""
+### solution by pokgopun@gmail.com
+
+def da(ints: tuple[int]) -> int:
+ l = len(ints)
+ lst = sorted(ints)
+ avgs = []
+ for i in range(int(l/2)):
+ avgs.append((lst[i]+lst[l-1-i])/2)
+ return len(set(avgs))
+
+import unittest
+
+class TestDa(unittest.TestCase):
+ def test(self):
+ for inpt, otpt in {
+ (1, 2, 4, 3, 5, 6): 1,
+ (0, 2, 4, 8, 3, 5): 2,
+ (7, 3, 1, 0, 5, 9): 2,
+ }.items():
+ self.assertEqual(da(inpt), otpt)
+
+unittest.main()
diff --git a/challenge-321/pokgopun/python/ch-2.py b/challenge-321/pokgopun/python/ch-2.py
new file mode 100644
index 0000000000..befadf0ef2
--- /dev/null
+++ b/challenge-321/pokgopun/python/ch-2.py
@@ -0,0 +1,74 @@
+### https://theweeklychallenge.org/blog/perl-weekly-challenge-321/
+"""
+
+Task 2: Backspace Compare
+
+Submitted by: [45]Mohammad Sajid Anwar
+ __________________________________________________________________
+
+ You are given two strings containing zero or more #.
+
+ Write a script to return true if the two given strings are same by
+ treating # as backspace.
+
+Example 1
+
+Input: $str1 = "ab#c"
+ $str2 = "ad#c"
+Output: true
+
+For first string, we remove "b" as it is followed by "#".
+For second string, we remove "d" as it is followed by "#".
+In the end both strings became the same.
+
+Example 2
+
+Input: $str1 = "ab##"
+ $str2 = "a#b#"
+Output: true
+
+Example 3
+
+Input: $str1 = "a#b"
+ $str2 = "c"
+Output: false
+ __________________________________________________________________
+
+ Last date to submit the solution 23:59 (UK Time) Sunday 18th May 2025.
+ __________________________________________________________________
+
+SO WHAT DO YOU THINK ?
+"""
+### solution by pokgopun@gmail.com
+
+def bc(str1: str, str2: str) -> bool:
+ return ab(str1) == ab(str2)
+
+def ab(string: str) -> str:
+ lst = list(string)
+ l = len(lst)
+ i = 0
+ while i < l:
+ if lst[i] == "#":
+ lst.pop(i)
+ l -= 1
+ if i > 0:
+ lst.pop(i-1)
+ l -= 1
+ i -= 1
+ else:
+ i += 1
+ return "".join(lst)
+
+import unittest
+
+class TestBc(unittest.TestCase):
+ def test(self):
+ for (str1, str2), otpt in {
+ ("ab#c", "ad#c"): True,
+ ("ab##", "a#b#"): True,
+ ("a#b", "c"): False,
+ }.items():
+ self.assertEqual(bc(str1,str2),otpt)
+
+unittest.main()
diff --git a/challenge-321/roger-bell-west/crystal/ch-1.cr b/challenge-321/roger-bell-west/crystal/ch-1.cr
new file mode 100755
index 0000000000..6b6a947474
--- /dev/null
+++ b/challenge-321/roger-bell-west/crystal/ch-1.cr
@@ -0,0 +1,24 @@
+#! /usr/bin/crystal
+
+def distinctaverage(a0)
+ a = a0.sort
+ offset = a.size - 1
+ res = Set(Int32).new
+ 0.upto(a.size / 2 - 1) do |i|
+ res.add(a[i] + a[offset - i])
+ end
+ res.size
+end
+
+require "spec"
+describe "distinctaverage" do
+ it "test_ex1" do
+ distinctaverage([1, 2, 4, 3, 5, 6]).should eq 1
+ end
+ it "test_ex2" do
+ distinctaverage([0, 2, 4, 8, 3, 5]).should eq 2
+ end
+ it "test_ex3" do
+ distinctaverage([7, 3, 1, 0, 5, 9]).should eq 2
+ end
+end
diff --git a/challenge-321/roger-bell-west/crystal/ch-2.cr b/challenge-321/roger-bell-west/crystal/ch-2.cr
new file mode 100755
index 0000000000..2797e896d0
--- /dev/null
+++ b/challenge-321/roger-bell-west/crystal/ch-2.cr
@@ -0,0 +1,30 @@
+#! /usr/bin/crystal
+
+def backspacecompare(a, b)
+ sa = Array(String).new
+ [a, b].each do |i|
+ oa = Array(Char).new
+ i.chars.each do |c|
+ if c == '#'
+ oa.pop
+ else
+ oa.push(c)
+ end
+ end
+ sa.push(oa.join(""))
+ end
+ sa[0] == sa[1]
+end
+
+require "spec"
+describe "backspacecompare" do
+ it "test_ex1" do
+ backspacecompare("ab#c", "ad#c").should eq true
+ end
+ it "test_ex2" do
+ backspacecompare("ab##", "a#b#").should eq true
+ end
+ it "test_ex3" do
+ backspacecompare("a#b", "c").should eq false
+ end
+end
diff --git a/challenge-321/roger-bell-west/javascript/ch-1.js b/challenge-321/roger-bell-west/javascript/ch-1.js
new file mode 100755
index 0000000000..d6f078281e
--- /dev/null
+++ b/challenge-321/roger-bell-west/javascript/ch-1.js
@@ -0,0 +1,36 @@
+#! /usr/bin/node
+
+"use strict"
+
+function distinctaverage(a0) {
+ let a = [...a0];
+ a.sort(function(a,b) {
+ return a-b;
+ });
+ const offset = a.length - 1;
+ const limit = Math.floor(a.length / 2);
+ let res = new Set;
+ for (let i = 0; i < limit; i++) {
+ res.add(a[i] + a[offset - i]);
+ }
+ return res.size;
+}
+
+if (distinctaverage([1, 2, 4, 3, 5, 6]) == 1) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (distinctaverage([0, 2, 4, 8, 3, 5]) == 2) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (distinctaverage([7, 3, 1, 0, 5, 9]) == 2) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-321/roger-bell-west/javascript/ch-2.js b/challenge-321/roger-bell-west/javascript/ch-2.js
new file mode 100755
index 0000000000..1a58b683d0
--- /dev/null
+++ b/challenge-321/roger-bell-west/javascript/ch-2.js
@@ -0,0 +1,38 @@
+#! /usr/bin/node
+
+"use strict"
+
+function backspacecompare(a, b) {
+ let sa = [];
+ for (let i of [a, b]) {
+ let oa = [];
+ i.split("").forEach((c, _) => {
+ if (c == '#') {
+ oa.pop();
+ } else {
+ oa.push(c);
+ }
+ });
+ sa.push(oa.join(''));
+ }
+ return sa[0] == sa[1];
+}
+
+if (backspacecompare('ab#c', 'ad#c')) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (backspacecompare('ab##', 'a#b#')) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (!backspacecompare('a#b', 'c')) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-321/roger-bell-west/kotlin/ch-1.kt b/challenge-321/roger-bell-west/kotlin/ch-1.kt
new file mode 100644
index 0000000000..639e145135
--- /dev/null
+++ b/challenge-321/roger-bell-west/kotlin/ch-1.kt
@@ -0,0 +1,33 @@
+fun distinctaverage(a0: List<Int>): Int {
+ val a = a0.sorted()
+ val offset = a.size - 1
+ val limit = a.size / 2
+ var res = mutableSetOf<Int>()
+ for (i in 0 .. limit - 1) {
+ res.add(a[i] + a[offset - i])
+ }
+ return res.size
+}
+
+fun main() {
+
+ if (distinctaverage(listOf(1, 2, 4, 3, 5, 6)) == 1) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (distinctaverage(listOf(0, 2, 4, 8, 3, 5)) == 2) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (distinctaverage(listOf(7, 3, 1, 0, 5, 9)) == 2) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-321/roger-bell-west/kotlin/ch-2.kt b/challenge-321/roger-bell-west/kotlin/ch-2.kt
new file mode 100644
index 0000000000..41f1d76487
--- /dev/null
+++ b/challenge-321/roger-bell-west/kotlin/ch-2.kt
@@ -0,0 +1,38 @@
+fun backspacecompare(a: String, b: String): Boolean {
+ var sa = ArrayList<String>()
+ for (i in listOf(a, b)) {
+ var oa = ArrayList<Char>()
+ i.toCharArray().forEach() {c ->
+ if (c == '#') {
+ oa.removeLast()
+ } else {
+ oa.add(c)
+ }
+ }
+ sa.add(oa.joinToString(""))
+ }
+ return sa[0] == sa[1]
+}
+
+fun main() {
+
+ if (backspacecompare("ab#c", "ad#c")) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (backspacecompare("ab##", "a#b#")) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (!backspacecompare("a#b", "c")) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-321/roger-bell-west/lua/ch-1.lua b/challenge-321/roger-bell-west/lua/ch-1.lua
new file mode 100755
index 0000000000..1445c9ad90
--- /dev/null
+++ b/challenge-321/roger-bell-west/lua/ch-1.lua
@@ -0,0 +1,42 @@
+#! /usr/bin/lua
+
+function propersize(t)
+ local l=0
+ for k,v in pairs(t) do
+ l = l + 1
+ end
+ return l
+end
+
+function distinctaverage(a0)
+ local a = a0
+ table.sort(a,function (aa, bb) return aa < bb end)
+ local offset = #a + 1
+ local res = {}
+ for i = 1, #a / 2 do
+ res[a[i] + a[offset - i]] = true
+ end
+ return propersize(res)
+end
+
+if distinctaverage({1, 2, 4, 3, 5, 6}) == 1 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if distinctaverage({0, 2, 4, 8, 3, 5}) == 2 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if distinctaverage({7, 3, 1, 0, 5, 9}) == 2 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-321/roger-bell-west/lua/ch-2.lua b/challenge-321/roger-bell-west/lua/ch-2.lua
new file mode 100755
index 0000000000..60d4d80aa7
--- /dev/null
+++ b/challenge-321/roger-bell-west/lua/ch-2.lua
@@ -0,0 +1,58 @@
+#! /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 backspacecompare(a, b)
+ local sa = {}
+ for _, i in ipairs({a, b}) do
+ local oa = {}
+ for _n, c in ipairs(split(i)) do
+ if c == "#" then
+ table.remove(oa, #oa)
+ else
+ table.insert(oa, c)
+ end
+ end
+ table.insert(sa, join(oa))
+ end
+ return sa[1] == sa[2]
+end
+
+if backspacecompare("ab#c", "ad#c") then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if backspacecompare("ab##", "a#b#") then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if not backspacecompare("a#b", "c") then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-321/roger-bell-west/perl/ch-1.pl b/challenge-321/roger-bell-west/perl/ch-1.pl
new file mode 100755
index 0000000000..7463ba8611
--- /dev/null
+++ b/challenge-321/roger-bell-west/perl/ch-1.pl
@@ -0,0 +1,21 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 3;
+
+is(distinctaverage([1, 2, 4, 3, 5, 6]), 1, 'example 1');
+is(distinctaverage([0, 2, 4, 8, 3, 5]), 2, 'example 2');
+is(distinctaverage([7, 3, 1, 0, 5, 9]), 2, 'example 3');
+
+sub distinctaverage($a0) {
+ my @a = sort { $::a <=> $::b } @{$a0};
+ my $offset = scalar @a - 1;
+ my %res;
+ foreach my $i (0 .. (scalar @a) / 2) {
+ $res{$a[$i] + $a[$offset - $i]} = 1;
+ }
+ scalar keys %res;
+}
diff --git a/challenge-321/roger-bell-west/perl/ch-2.pl b/challenge-321/roger-bell-west/perl/ch-2.pl
new file mode 100755
index 0000000000..391a91eb6f
--- /dev/null
+++ b/challenge-321/roger-bell-west/perl/ch-2.pl
@@ -0,0 +1,27 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 3;
+
+is(backspacecompare('ab#c', 'ad#c'), 1, 'example 1');
+is(backspacecompare('ab##', 'a#b#'), 1, 'example 2');
+is(backspacecompare('a#b', 'c'), 0, 'example 3');
+
+sub backspacecompare($a, $b) {
+ my @sa;
+ foreach my $i ($a, $b) {
+ my @oa;
+ foreach my $c (split '', $i) {
+ if ($c eq '#') {
+ pop @oa;
+ } else {
+ push @oa, $c;
+ }
+ }
+ push @sa, join('', @oa);
+ }
+ ($sa[0] eq $sa[1])?1:0;
+}
diff --git a/challenge-321/roger-bell-west/postscript/ch-1.ps b/challenge-321/roger-bell-west/postscript/ch-1.ps
new file mode 100644
index 0000000000..827ad4ffed
--- /dev/null
+++ b/challenge-321/roger-bell-west/postscript/ch-1.ps
@@ -0,0 +1,153 @@
+%!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.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.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
+
+/quicksort {
+ { quicksort.cmp } quicksort.with_comparator
+} 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
+
+/keys { % dict -> array of dict keys
+ [ exch
+ {
+ pop
+ } 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
+
+
+% end included library code
+
+/distinctaverage {
+ 0 dict begin
+ quicksort
+ /a exch def
+ /offset a length 1 sub def
+ /res 0 dict def
+ 0 1 a length 2 idiv 1 sub {
+ /i exch def
+ res a i get a offset i sub get add true put
+ } for
+ res keys length
+ end
+} bind def
+
+(distinctaverage) test.start
+[1 2 4 3 5 6] distinctaverage 1 eq test
+[0 2 4 8 3 5] distinctaverage 2 eq test
+[7 3 1 0 5 9] distinctaverage 2 eq test
+test.end
diff --git a/challenge-321/roger-bell-west/postscript/ch-2.ps b/challenge-321/roger-bell-west/postscript/ch-2.ps
new file mode 100644
index 0000000000..992dc0afb0
--- /dev/null
+++ b/challenge-321/roger-bell-west/postscript/ch-2.ps
@@ -0,0 +1,120 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/s2a {
+ [ exch { } 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
+
+/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 {
+ /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
+
+/backspacecompare {
+ 2 array astore
+ {
+ [ exch
+ s2a {
+ dup