aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Bell_West <roger@firedrake.org>2024-02-20 11:37:46 +0000
committerRoger Bell_West <roger@firedrake.org>2024-02-20 11:37:46 +0000
commit4de649256f3bad9f0331d183c7efcc7ce83b4fb0 (patch)
tree8607bd91eda90a9921465d1a340225eee559bf20
parentd56f5846adcf3864f7b9dd2426d85ae68579729e (diff)
downloadperlweeklychallenge-club-4de649256f3bad9f0331d183c7efcc7ce83b4fb0.tar.gz
perlweeklychallenge-club-4de649256f3bad9f0331d183c7efcc7ce83b4fb0.tar.bz2
perlweeklychallenge-club-4de649256f3bad9f0331d183c7efcc7ce83b4fb0.zip
RogerBW solutions for challenge no. 257
-rwxr-xr-xchallenge-257/roger-bell-west/javascript/ch-1.js69
-rwxr-xr-xchallenge-257/roger-bell-west/javascript/ch-2.js125
-rw-r--r--challenge-257/roger-bell-west/kotlin/ch-1.kt40
-rw-r--r--challenge-257/roger-bell-west/kotlin/ch-2.kt95
-rwxr-xr-xchallenge-257/roger-bell-west/lua/ch-1.lua75
-rwxr-xr-xchallenge-257/roger-bell-west/lua/ch-2.lua125
-rwxr-xr-xchallenge-257/roger-bell-west/perl/ch-1.pl24
-rwxr-xr-xchallenge-257/roger-bell-west/perl/ch-2.pl53
-rw-r--r--challenge-257/roger-bell-west/postscript/ch-1.ps228
-rw-r--r--challenge-257/roger-bell-west/postscript/ch-2.ps313
-rwxr-xr-xchallenge-257/roger-bell-west/python/ch-1.py28
-rwxr-xr-xchallenge-257/roger-bell-west/python/ch-2.py57
-rwxr-xr-xchallenge-257/roger-bell-west/raku/ch-1.p622
-rwxr-xr-xchallenge-257/roger-bell-west/raku/ch-2.p650
-rwxr-xr-xchallenge-257/roger-bell-west/ruby/ch-1.rb34
-rwxr-xr-xchallenge-257/roger-bell-west/ruby/ch-2.rb74
-rwxr-xr-xchallenge-257/roger-bell-west/rust/ch-1.rs36
-rwxr-xr-xchallenge-257/roger-bell-west/rust/ch-2.rs127
-rw-r--r--challenge-257/roger-bell-west/scala/ch-1.scala41
-rw-r--r--challenge-257/roger-bell-west/scala/ch-2.scala98
-rw-r--r--challenge-257/roger-bell-west/tests.yaml163
21 files changed, 1877 insertions, 0 deletions
diff --git a/challenge-257/roger-bell-west/javascript/ch-1.js b/challenge-257/roger-bell-west/javascript/ch-1.js
new file mode 100755
index 0000000000..f7d2801884
--- /dev/null
+++ b/challenge-257/roger-bell-west/javascript/ch-1.js
@@ -0,0 +1,69 @@
+#! /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 smallerthancurrent(a) {
+ let s = [...a];
+ s.sort(function(a,b) {
+ return a-b;
+ });
+ let l = new Map;
+ s.forEach((n, i) => {
+ if (!l.has(n)) {
+ l.set(n, i);
+ }
+ });
+ return a.map(n => l.get(n));
+}
+
+if (deepEqual(smallerthancurrent([5, 2, 1, 6]), [2, 1, 0, 3])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(smallerthancurrent([1, 2, 0, 3]), [1, 2, 0, 3])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(smallerthancurrent([0, 1]), [0, 1])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(smallerthancurrent([9, 4, 9, 2]), [2, 1, 2, 0])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-257/roger-bell-west/javascript/ch-2.js b/challenge-257/roger-bell-west/javascript/ch-2.js
new file mode 100755
index 0000000000..30d85505c0
--- /dev/null
+++ b/challenge-257/roger-bell-west/javascript/ch-2.js
@@ -0,0 +1,125 @@
+#! /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 reducedrowechelon(a) {
+ let leadingone = [];
+ let valid = true;
+ for (let row of a) {
+ let lp = -1;
+ row.forEach((cell, cn) => {
+ if (lp == -1) {
+ if (cell == 1) {
+ lp = cn;
+ } else if (cell != 0) {
+ valid = false;
+ }
+ }
+ });
+ leadingone.push(lp);
+ }
+ if (!valid) {
+ return false;
+ }
+ while (leadingone[leadingone.length-1] == -1) {
+ leadingone.pop();
+ }
+ let c = [...leadingone];
+ c.sort(function(a,b) {
+ return a-b;
+ });
+ if (c[0] == -1) {
+ return false;
+ }
+ if (!deepEqual(c, leadingone)) {
+ return false;
+ }
+ for (let i of c) {
+ let col = a.map(r => r[i]);
+ col.sort(function(a,b) {
+ return a-b;
+ });
+ if (col[col.length-1] != 1 ||
+ col[col.length-2] != 0 ||
+ col[0] != 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+if (!reducedrowechelon([[1, 1, 0], [0, 1, 0], [0, 0, 0]])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (reducedrowechelon([[0, 1, -2, 0, 1], [0, 0, 0, 1, 3], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (reducedrowechelon([[1, 0, 0, 4], [0, 1, 0, 7], [0, 0, 1, -1]])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (!reducedrowechelon([[0, 1, -2, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 1, 3], [0, 0, 0, 0, 0]])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (!reducedrowechelon([[0, 1, 0], [0, 1, 0], [0, 0, 0]])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (!reducedrowechelon([[4, 0, 0, 0], [0, 1, 0, 7], [0, 0, 1, -1]])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (!reducedrowechelon([[1, 0, 0, 4], [1, 0, 0, 7], [0, 0, 1, -1]])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (!reducedrowechelon([[1, -2, 0, 4], [0, 1, 0, 7], [0, 0, 1, -1]])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-257/roger-bell-west/kotlin/ch-1.kt b/challenge-257/roger-bell-west/kotlin/ch-1.kt
new file mode 100644
index 0000000000..09a1b389ba
--- /dev/null
+++ b/challenge-257/roger-bell-west/kotlin/ch-1.kt
@@ -0,0 +1,40 @@
+fun smallerthancurrent(a: List<Int>): List<Int> {
+ var s = ArrayList(a)
+ s.sort()
+ var l = mutableMapOf<Int, Int>()
+ s.forEachIndexed {i, n ->
+ if (!l.contains(n)) {
+ l.put(n, i)
+ }
+ }
+ return a.map { l.getValue(it) }.toList()
+}
+
+fun main() {
+
+ if (smallerthancurrent(listOf(5, 2, 1, 6)) == listOf(2, 1, 0, 3)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (smallerthancurrent(listOf(1, 2, 0, 3)) == listOf(1, 2, 0, 3)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (smallerthancurrent(listOf(0, 1)) == listOf(0, 1)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (smallerthancurrent(listOf(9, 4, 9, 2)) == listOf(2, 1, 2, 0)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-257/roger-bell-west/kotlin/ch-2.kt b/challenge-257/roger-bell-west/kotlin/ch-2.kt
new file mode 100644
index 0000000000..f5d3abccda
--- /dev/null
+++ b/challenge-257/roger-bell-west/kotlin/ch-2.kt
@@ -0,0 +1,95 @@
+
+fun reducedrowechelon(a: List<List<Int>>): Boolean {
+ var leadingone = ArrayList<Int>()
+ var valid = true
+ for (row in a) {
+ var lp = -1
+ row.forEachIndexed{cn, cell ->
+ if (lp == -1) {
+ if (cell == 1) {
+ lp = cn
+ } else if (cell != 0) {
+ valid = false
+ }
+ }
+ }
+ leadingone.add(lp)
+ if (!valid) {
+ return false
+ }
+ }
+ while (leadingone[leadingone.size-1] == -1) {
+ leadingone.removeLast()
+ }
+ var c = ArrayList(leadingone)
+ c.sort()
+ if (c[0] == -1) {
+ return false
+ }
+ if (c != leadingone) {
+ return false
+ }
+ for (i in c) {
+ var col = ArrayList(a.map { it[i] })
+ col.sort()
+ if (col[col.size-1] != 1 ||
+ col[col.size-2] != 0 ||
+ col[0] != 0) {
+ return false
+ }
+ }
+ return true
+}
+
+fun main() {
+
+ if (!reducedrowechelon(listOf(listOf(1, 1, 0), listOf(0, 1, 0), listOf(0, 0, 0)))) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (reducedrowechelon(listOf(listOf(0, 1, -2, 0, 1), listOf(0, 0, 0, 1, 3), listOf(0, 0, 0, 0, 0), listOf(0, 0, 0, 0, 0)))) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (reducedrowechelon(listOf(listOf(1, 0, 0, 4), listOf(0, 1, 0, 7), listOf(0, 0, 1, -1)))) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (!reducedrowechelon(listOf(listOf(0, 1, -2, 0, 1), listOf(0, 0, 0, 0, 0), listOf(0, 0, 0, 1, 3), listOf(0, 0, 0, 0, 0)))) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (!reducedrowechelon(listOf(listOf(0, 1, 0), listOf(0, 1, 0), listOf(0, 0, 0)))) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (!reducedrowechelon(listOf(listOf(4, 0, 0, 0), listOf(0, 1, 0, 7), listOf(0, 0, 1, -1)))) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (!reducedrowechelon(listOf(listOf(1, 0, 0, 4), listOf(1, 0, 0, 7), listOf(0, 0, 1, -1)))) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (!reducedrowechelon(listOf(listOf(1, -2, 0, 4), listOf(0, 1, 0, 7), listOf(0, 0, 1, -1)))) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-257/roger-bell-west/lua/ch-1.lua b/challenge-257/roger-bell-west/lua/ch-1.lua
new file mode 100755
index 0000000000..fbd0bc40b4
--- /dev/null
+++ b/challenge-257/roger-bell-west/lua/ch-1.lua
@@ -0,0 +1,75 @@
+#! /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 smallerthancurrent(a)
+ local s = a
+ table.sort(s, function (i, j) return i < j end)
+ local l = {}
+ for i, n in ipairs(s) do
+ if l[n] == nil then
+ l[n] = i
+ end
+ end
+ local out = {}
+ for _, n in ipairs(a) do
+ table.insert(out, l[n])
+ end
+ return out
+end
+
+if recursive_compare(smallerthancurrent({5, 2, 1, 6}), {2, 1, 0, 3}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(smallerthancurrent({1, 2, 0, 3}), {1, 2, 0, 3}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(smallerthancurrent({0, 1}), {0, 1}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(smallerthancurrent({9, 4, 9, 2}), {2, 1, 2, 0}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-257/roger-bell-west/lua/ch-2.lua b/challenge-257/roger-bell-west/lua/ch-2.lua
new file mode 100755
index 0000000000..436dc433e3
--- /dev/null
+++ b/challenge-257/roger-bell-west/lua/ch-2.lua
@@ -0,0 +1,125 @@
+#! /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 reducedrowechelon(a)
+ local leadingone = {}
+ for _, row in ipairs(a) do
+ local lp = -1
+ for cn, cell in ipairs(row) do
+ if cell == 1 then
+ lp = cn - 1
+ break
+ elseif cell ~= 0 then
+ return false
+ end
+ end
+ table.insert(leadingone, lp)
+ end
+ while leadingone[#leadingone] == -1 do
+ table.remove(leadingone)
+ end
+ local c = leadingone
+ table.sort(c, function (i, j) return i < j end)
+ if c[1] == -1 then
+ return false
+ end
+ if not recursive_compare(c, leadingone) then
+ return false
+ end
+ for _, i in ipairs(c) do
+ local col = {}
+ for _b, row in ipairs(a) do
+ table.insert(col, row[i + 1])
+ end
+ table.sort(col, function (i, j) return i < j end)
+ if col[#col] ~= 1 or col[#col - 1] ~= 0 or col[1] ~= 0 then
+ return false
+ end
+ end
+ return true
+end
+
+if not reducedrowechelon({{1, 1, 0}, {0, 1, 0}, {0, 0, 0}}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if reducedrowechelon({{0, 1, -2, 0, 1}, {0, 0, 0, 1, 3}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if reducedrowechelon({{1, 0, 0, 4}, {0, 1, 0, 7}, {0, 0, 1, -1}}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if not reducedrowechelon({{0, 1, -2, 0, 1}, {0, 0, 0, 0, 0}, {0, 0, 0, 1, 3}, {0, 0, 0, 0, 0}}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if not reducedrowechelon({{0, 1, 0}, {0, 1, 0}, {0, 0, 0}}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if not reducedrowechelon({{4, 0, 0, 0}, {0, 1, 0, 7}, {0, 0, 1, -1}}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if not reducedrowechelon({{1, 0, 0, 4}, {1, 0, 0, 7}, {0, 0, 1, -1}}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if not reducedrowechelon({{1, -2, 0, 4}, {0, 1, 0, 7}, {0, 0, 1, -1}}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-257/roger-bell-west/perl/ch-1.pl b/challenge-257/roger-bell-west/perl/ch-1.pl
new file mode 100755
index 0000000000..3ebebbc636
--- /dev/null
+++ b/challenge-257/roger-bell-west/perl/ch-1.pl
@@ -0,0 +1,24 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 4;
+
+is_deeply(smallerthancurrent([5, 2, 1, 6]), [2, 1, 0, 3], 'example 1');
+is_deeply(smallerthancurrent([1, 2, 0, 3]), [1, 2, 0, 3], 'example 2');
+is_deeply(smallerthancurrent([0, 1]), [0, 1], 'example 3');
+is_deeply(smallerthancurrent([9, 4, 9, 2]), [2, 1, 2, 0], 'example 4');
+
+sub smallerthancurrent($a) {
+ my %l;
+ my @s = sort {$::a <=> $::b} @{$a};
+ foreach my $i (0..$#s) {
+ my $n = $s[$i];
+ unless (exists $l{$n}) {
+ $l{$n} = $i;
+ }
+ }
+ return [map {$l{$_}} @{$a}];
+}
diff --git a/challenge-257/roger-bell-west/perl/ch-2.pl b/challenge-257/roger-bell-west/perl/ch-2.pl
new file mode 100755
index 0000000000..43a4621110
--- /dev/null
+++ b/challenge-257/roger-bell-west/perl/ch-2.pl
@@ -0,0 +1,53 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 8;
+use Test::Deep::NoTest;
+
+is(reducedrowechelon([[1, 1, 0], [0, 1, 0], [0, 0, 0]]), 0, 'example 1');
+is(reducedrowechelon([[0, 1, -2, 0, 1], [0, 0, 0, 1, 3], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]), 1, 'example 2');
+is(reducedrowechelon([[1, 0, 0, 4], [0, 1, 0, 7], [0, 0, 1, -1]]), 1, 'example 3');
+is(reducedrowechelon([[0, 1, -2, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 1, 3], [0, 0, 0, 0, 0]]), 0, 'example 4');
+is(reducedrowechelon([[0, 1, 0], [0, 1, 0], [0, 0, 0]]), 0, 'example 5');
+is(reducedrowechelon([[4, 0, 0, 0], [0, 1, 0, 7], [0, 0, 1, -1]]), 0, 'example 6');
+is(reducedrowechelon([[1, 0, 0, 4], [1, 0, 0, 7], [0, 0, 1, -1]]), 0, 'example 7');
+is(reducedrowechelon([[1, -2, 0, 4], [0, 1, 0, 7], [0, 0, 1, -1]]), 0, 'example 8');
+
+sub reducedrowechelon($a) {
+ my @leadingone;
+ foreach my $row (@{$a}) {
+ my $lp = -1;
+ foreach my $cn (0 .. $#{$row}) {
+ my $cell = $row->[$cn];
+ if ($cell == 1) {
+ $lp = $cn;
+ last;
+ } elsif ($cell != 0) {
+ return 0;
+ }
+ }
+ push @leadingone, $lp;
+ }
+ while ($leadingone[-1] == -1) {
+ pop @leadingone;
+ }
+ my @c = sort {$::a <=> $::b} @leadingone;
+ if ($c[0] == -1) {
+ return 0;
+ }
+ if (!eq_deeply(\@c, \@leadingone)) {
+ return 0;
+ }
+ foreach my $i (@c) {
+ my @col = sort {$::a <=> $::b} map {$_->[$i]} @{$a};
+ if ($col[-1] != 1 ||
+ $col[-2] != 0 ||
+ $col[0] != 0) {
+ return 0;
+ }
+ }
+ return 1;
+}
diff --git a/challenge-257/roger-bell-west/postscript/ch-1.ps b/challenge-257/roger-bell-west/postscript/ch-1.ps
new file mode 100644
index 0000000000..edaebf28b0
--- /dev/null
+++ b/challenge-257/roger-bell-west/postscript/ch-1.ps
@@ -0,0 +1,228 @@
+%!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
+
+/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
+
+/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
+
+/quicksort {
+ { quicksort.cmp } quicksort.with_comparator
+} 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.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
+
+/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
+
+/map { % array proc -> array
+ 2 dict begin
+ /p exch def
+ [ exch
+ {
+ p
+ } forall
+ ]
+ end
+} 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
+
+
+% end included library code
+
+/smallerthancurrent {
+ 0 dict begin
+ dup
+ /l 0 dict def
+ [ exch aload pop ] quicksort enumerate.array {
+ aload pop
+ /n exch def
+ /i exch def
+ l n known not {
+ l n i put
+ } if
+ } forall
+ { l exch get } map
+ end
+} bind def
+
+(smallerthancurrent) test.start
+[5 2 1 6] smallerthancurrent [2 1 0 3] deepeq test
+[1 2 0 3] smallerthancurrent [1 2 0 3] deepeq test
+[0 1] smallerthancurrent [0 1] deepeq test
+[9 4 9 2] smallerthancurrent [2 1 2 0] deepeq test
+test.end
diff --git a/challenge-257/roger-bell-west/postscript/ch-2.ps b/challenge-257/roger-bell-west/postscript/ch-2.ps
new file mode 100644
index 0000000000..ea6ed2bf63
--- /dev/null
+++ b/challenge-257/roger-bell-west/postscript/ch-2.ps
@@ -0,0 +1,313 @@
+%!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
+
+/map { % array proc -> array
+ 2 dict begin
+ /p exch def
+ [ exch
+ {
+ p
+ } forall
+ ]
+ end
+} 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.start {
+ print (:) print
+ /test.pass 0 def
+ /test.count 0 def
+} 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
+
+/apop.right { % [a b c] -> [a b] c
+ [ exch aload length 1 add 1 roll ] exch
+} 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
+
+/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
+
+/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
+
+/quicksort.main { % lo hi -> (null)
+ 3 dict begin
+ /hi exch def
+ /lo exch def
+ /