aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Bell_West <roger@firedrake.org>2024-05-21 13:24:25 +0100
committerRoger Bell_West <roger@firedrake.org>2024-05-21 13:24:25 +0100
commit934105849615c077f262a0dd4bbf8a5fa04e0307 (patch)
tree22e6fa3931b2fe63b2a9e12bc0d64dd6ed63e7e4
parented462bf99ed6fda013ab14d58855951ef13b05fa (diff)
downloadperlweeklychallenge-club-934105849615c077f262a0dd4bbf8a5fa04e0307.tar.gz
perlweeklychallenge-club-934105849615c077f262a0dd4bbf8a5fa04e0307.tar.bz2
perlweeklychallenge-club-934105849615c077f262a0dd4bbf8a5fa04e0307.zip
RogerBW solutions for challenge no. 270
-rwxr-xr-xchallenge-270/roger-bell-west/crystal/ch-1.cr45
-rwxr-xr-xchallenge-270/roger-bell-west/crystal/ch-2.cr49
-rwxr-xr-xchallenge-270/roger-bell-west/javascript/ch-1.js59
-rwxr-xr-xchallenge-270/roger-bell-west/javascript/ch-2.js48
-rw-r--r--challenge-270/roger-bell-west/kotlin/ch-1.kt47
-rw-r--r--challenge-270/roger-bell-west/kotlin/ch-2.kt52
-rwxr-xr-xchallenge-270/roger-bell-west/lua/ch-1.lua69
-rwxr-xr-xchallenge-270/roger-bell-west/lua/ch-2.lua59
-rwxr-xr-xchallenge-270/roger-bell-west/perl/ch-1.pl43
-rwxr-xr-xchallenge-270/roger-bell-west/perl/ch-2.pl41
-rw-r--r--challenge-270/roger-bell-west/postscript/ch-1.ps248
-rw-r--r--challenge-270/roger-bell-west/postscript/ch-2.ps215
-rwxr-xr-xchallenge-270/roger-bell-west/python/ch-1.py37
-rwxr-xr-xchallenge-270/roger-bell-west/python/ch-2.py41
-rwxr-xr-xchallenge-270/roger-bell-west/raku/ch-1.p640
-rwxr-xr-xchallenge-270/roger-bell-west/raku/ch-2.p639
-rwxr-xr-xchallenge-270/roger-bell-west/ruby/ch-1.rb51
-rwxr-xr-xchallenge-270/roger-bell-west/ruby/ch-2.rb55
-rwxr-xr-xchallenge-270/roger-bell-west/rust/ch-1.rs55
-rwxr-xr-xchallenge-270/roger-bell-west/rust/ch-2.rs50
-rw-r--r--challenge-270/roger-bell-west/scala/ch-1.scala47
-rw-r--r--challenge-270/roger-bell-west/scala/ch-2.scala54
-rw-r--r--challenge-270/roger-bell-west/tests.json42
23 files changed, 1486 insertions, 0 deletions
diff --git a/challenge-270/roger-bell-west/crystal/ch-1.cr b/challenge-270/roger-bell-west/crystal/ch-1.cr
new file mode 100755
index 0000000000..202efa421e
--- /dev/null
+++ b/challenge-270/roger-bell-west/crystal/ch-1.cr
@@ -0,0 +1,45 @@
+#! /usr/bin/crystal
+
+def validator(a0 : Array(Int32)) : Int32?
+ a = a0.sort
+ l = a.size
+ if a[0] == 0 && a[l - 2] == 0 && a[l - 1] == 1
+ (0 ... l).each do |i|
+ if a0[i] == 1
+ return i
+ end
+ end
+ end
+ nil
+end
+
+def specialpositions(a : Array(Array(Int32))) : Int32
+ vr = Set(Tuple(Int32, Int32)).new
+ xs = Set(Int32).new
+ a.each_with_index do |row, y|
+ x = validator(row) || -1
+ if x
+ vr.add({y, x})
+ xs.add(x)
+ end
+ end
+ xd = Set(Int32).new
+ xs.each do |x|
+ c = a.map { |r| r[x] }
+ unless validator(c)
+ xd.add(x)
+ end
+ end
+ xs -= xd
+ vr.select { | (y, x) | xs.includes?(x) }.size
+end
+
+require "spec"
+describe "#tmpl_var name=function>" do
+ it "test_ex1" do
+ specialpositions([[1, 0, 0], [0, 0, 1], [1, 0, 0]]).should eq 1
+ end
+ it "test_ex2" do
+ specialpositions([[1, 0, 0], [0, 1, 0], [0, 0, 1]]).should eq 3
+ end
+end
diff --git a/challenge-270/roger-bell-west/crystal/ch-2.cr b/challenge-270/roger-bell-west/crystal/ch-2.cr
new file mode 100755
index 0000000000..50e1ac65ae
--- /dev/null
+++ b/challenge-270/roger-bell-west/crystal/ch-2.cr
@@ -0,0 +1,49 @@
+#! /usr/bin/crystal
+
+struct Op
+ property a, cost
+
+ def initialize(@a : Array(Int32), @cost : Int32)
+ end
+end
+
+def equalizearray(a0 : Array(Int32), x : Int32, y : Int32) : Int32?
+ a = a0.sort
+ limit = a[-1]
+ queue = Deque(Op).new
+ queue.push(Op.new(a, 0))
+ mc : Int32 | Nil = nil
+ while queue.size > 0
+ op = queue.shift
+ if !mc || mc > op.cost
+ if op.a[0] == op.a[-1]
+ mc = op.cost
+ else
+ p = op.a.dup
+ p[0] += 1
+ if p[0] <= limit
+ p = p.sort
+ queue.push(Op.new(p, op.cost + x))
+ q = op.a.dup
+ q[0] += 1
+ q[1] += 1
+ if q[1] <= limit
+ q = q.sort
+ queue.push(Op.new(q, op.cost + y))
+ end
+ end
+ end
+ end
+ end
+ mc
+end
+
+require "spec"
+describe "#tmpl_var name=function>" do
+ it "test_ex1" do
+ equalizearray([4, 1], 3, 2).should eq 9
+ end
+ it "test_ex2" do
+ equalizearray([2, 3, 3, 3, 5], 2, 1).should eq 6
+ end
+end
diff --git a/challenge-270/roger-bell-west/javascript/ch-1.js b/challenge-270/roger-bell-west/javascript/ch-1.js
new file mode 100755
index 0000000000..85f32b13b1
--- /dev/null
+++ b/challenge-270/roger-bell-west/javascript/ch-1.js
@@ -0,0 +1,59 @@
+#! /usr/bin/node
+
+"use strict"
+
+function validator(a0) {
+ let a = [...a0];
+ a.sort();
+ let l = a.length;
+ if (a[0] == 0 && a[l - 2] == 0 && a[l - 1] == 1) {
+ for (let i = 0; i < l; i++) {
+ if (a0[i] == 1) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+function specialpositions(a) {
+ let vr = new Array;
+ let xs = new Set;
+ a.forEach((row, y) => {
+ let x = validator(row);
+ if (x > -1) {
+ vr.push([y, x]);
+ xs.add(x);
+ }
+ });
+ let xd = new Set;
+ for (let x of xs) {
+ let c = a.map(r => r[x]);
+ if (validator(c) == -1) {
+ xd.add(x);
+ }
+ }
+ for (let x of xd) {
+ xs.delete(x);
+ }
+ let t = 0;
+ for (let [y, x] of vr) {
+ if (xs.has(x)) {
+ t++;
+ }
+ }
+ return t;
+}
+
+if (specialpositions([[1, 0, 0], [0, 0, 1], [1, 0, 0]]) == 1) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (specialpositions([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) == 3) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-270/roger-bell-west/javascript/ch-2.js b/challenge-270/roger-bell-west/javascript/ch-2.js
new file mode 100755
index 0000000000..423a73cbd7
--- /dev/null
+++ b/challenge-270/roger-bell-west/javascript/ch-2.js
@@ -0,0 +1,48 @@
+#! /usr/bin/node
+
+"use strict"
+
+function equalizearray(a0, x, y) {
+ let a = [...a0];
+ a.sort();
+ const limit = a[a.length - 1];
+ let queue = [];
+ queue.push([a, 0]);
+ let mc = -1;
+ while (queue.length > 0) {
+ const op = queue.shift();
+ if (mc ==-1 || mc > op[1]) {
+ if (op[0][0] == op[0][op[0].length - 1]) {
+ mc = op[1];
+ } else {
+ let p = [...op[0]];
+ p[0]++;
+ if (p[0] <= limit) {
+ p.sort();
+ queue.push([p, op[1] + x]);
+ let q = [...op[0]];
+ q[0]++;
+ q[1]++;
+ if (q[1] <= limit) {
+ q.sort();
+ queue.push([q, op[1] + y]);
+ }
+ }
+ }
+ }
+ }
+ return mc
+}
+
+if (equalizearray([4, 1], 3, 2) == 9) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (equalizearray([2, 3, 3, 3, 5], 2, 1) == 6) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-270/roger-bell-west/kotlin/ch-1.kt b/challenge-270/roger-bell-west/kotlin/ch-1.kt
new file mode 100644
index 0000000000..cb2deaf1ee
--- /dev/null
+++ b/challenge-270/roger-bell-west/kotlin/ch-1.kt
@@ -0,0 +1,47 @@
+fun validator(a0: List<Int>): Int {
+ val a = a0.sorted()
+ val l = a.size
+ if (a[0] == 0 && a[l - 2] == 0 && a[l - 1] == 1) {
+ return a0.indexOf(1)
+ } else {
+ return -1
+ }
+}
+
+fun specialpositions(a: List<List<Int>>): Int {
+ var vr = mutableSetOf<Pair<Int, Int>>()
+ var xs = mutableSetOf<Int>()
+ a.forEachIndexed{y, row ->
+ val x = validator(row)
+ if (x > -1) {
+ vr.add(Pair(y, x))
+ xs.add(x)
+ }
+ }
+ var xd = mutableSetOf<Int>()
+ for (x in xs) {
+ val c = a.map{ it[x] }.toList()
+ if (validator(c) == -1) {
+ xd.add(x)
+ }
+ }
+ xs.removeAll(xd)
+ return vr.filter{xs.contains(it.second)}.size
+}
+
+fun main() {
+
+ if (specialpositions(listOf(listOf(1, 0, 0), listOf(0, 0, 1), listOf(1, 0, 0))) == 1) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (specialpositions(listOf(listOf(1, 0, 0), listOf(0, 1, 0), listOf(0, 0, 1))) == 3) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-270/roger-bell-west/kotlin/ch-2.kt b/challenge-270/roger-bell-west/kotlin/ch-2.kt
new file mode 100644
index 0000000000..a0bbfba4f3
--- /dev/null
+++ b/challenge-270/roger-bell-west/kotlin/ch-2.kt
@@ -0,0 +1,52 @@
+class Op(
+ var a: List<Int>,
+ var cost: Int
+) {}
+
+fun equalizearray(a0: List<Int>, x: Int, y: Int): Int {
+ val a = a0.sorted()
+ val limit = a.last()
+ val queue = ArrayDeque<Op>()
+ queue.add(Op(a, 0))
+ var mc = -1
+ while (queue.size > 0) {
+ val op = queue.removeFirst()
+ if (mc == -1 || mc > op.cost) {
+ if (op.a[0] == op.a.last()) {
+ mc = op.cost
+ } else {
+ var p = ArrayList(op.a)
+ p[0] += 1
+ if (p[0] <= limit) {
+ p.sort()
+ queue.add(Op(p.toList(), op.cost + x))
+ var q = ArrayList(op.a)
+ q[0] += 1
+ q[1] += 1
+ if (q[1] <= limit) {
+ q.sort()
+ queue.add(Op(q.toList(), op.cost + y))
+ }
+ }
+ }
+ }
+ }
+ return mc
+}
+
+fun main() {
+
+ if (equalizearray(listOf(4, 1), 3, 2) == 9) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (equalizearray(listOf(2, 3, 3, 3, 5), 2, 1) == 6) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-270/roger-bell-west/lua/ch-1.lua b/challenge-270/roger-bell-west/lua/ch-1.lua
new file mode 100755
index 0000000000..153d643c5c
--- /dev/null
+++ b/challenge-270/roger-bell-west/lua/ch-1.lua
@@ -0,0 +1,69 @@
+#! /usr/bin/lua
+
+function deepcopy(src)
+ local dst = {}
+ for k, v in pairs(src) do
+ if type(v) == "table" then
+ v = deepcopy(v)
+ end
+ dst[k] = v
+ end
+ return dst
+end
+
+function validator(a0)
+ local a = deepcopy(a0)
+ table.sort(a)
+ local l = #a
+ if a[1] == 0 and a[l - 1] == 0 and a[l] == 1 then
+ for i = 1, l do
+ if a0[i] == 1 then
+ return i
+ end
+ end
+ end
+ return 0
+end
+
+function specialpositions(a)
+ local vr = {}
+ local xs = {}
+ for y, row in ipairs(a) do
+ local x = validator(row)
+ if x > 0 then
+ table.insert(vr, {y, x})
+ xs[x] = true
+ end
+ end
+ for x, _ in pairs(xs) do
+ local c = {}
+ for _, row in ipairs(a) do
+ table.insert(c, row[x])
+ end
+ if validator(c) == 0 then
+ xs[x] = nil
+ end
+ end
+ local count = 0
+ for _, yx in ipairs(vr) do
+ if xs[yx[1]] ~= nil then
+ count = count + 1
+ end
+ end
+ return count
+end
+
+if specialpositions({{1, 0, 0}, {0, 0, 1}, {1, 0, 0}}) == 1 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if specialpositions({{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}) == 3 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-270/roger-bell-west/lua/ch-2.lua b/challenge-270/roger-bell-west/lua/ch-2.lua
new file mode 100755
index 0000000000..8fc9e78694
--- /dev/null
+++ b/challenge-270/roger-bell-west/lua/ch-2.lua
@@ -0,0 +1,59 @@
+#! /usr/bin/lua
+
+function deepcopy(src)
+ local dst = {}
+ for k, v in pairs(src) do
+ if type(v) == "table" then
+ v = deepcopy(v)
+ end
+ dst[k] = v
+ end
+ return dst
+end
+
+function equalizearray(a0, x, y)
+ local a = deepcopy(a0)
+ table.sort(a)
+ local limit = a[#a]
+ local queue = {}
+ table.insert(queue, {a, 0})
+ mc = -1
+ while #queue > 0 do
+ local op = table.remove(queue, 1)
+ if mc == -1 or mc > op[2] then
+ if op[1][1] == op[1][#op[1]] then
+ mc = op[2]
+ else
+ local p = deepcopy(op[1])
+ p[1] = p[1] + 1
+ if p[1] <= limit then
+ table.sort(p)
+ table.insert(queue, {p, op[2] + x})
+ local q = deepcopy(op[1])
+ q[1] = q[1] + 1
+ q[2] = q[2] + 1
+ if q[2] <= limit then
+ table.sort(q)
+ table.insert(queue, {q, op[2] + y})
+ end
+ end
+ end
+ end
+ end
+ return mc
+end
+
+if equalizearray({4, 1}, 3, 2) == 9 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if equalizearray({2, 3, 3, 3, 5}, 2, 1) == 6 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-270/roger-bell-west/perl/ch-1.pl b/challenge-270/roger-bell-west/perl/ch-1.pl
new file mode 100755
index 0000000000..a610c9c29e
--- /dev/null
+++ b/challenge-270/roger-bell-west/perl/ch-1.pl
@@ -0,0 +1,43 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 2;
+
+is(specialpositions([[1, 0, 0], [0, 0, 1], [1, 0, 0]]), 1, 'example 1');
+is(specialpositions([[1, 0, 0], [0, 1, 0], [0, 0, 1]]), 3, 'example 2');
+
+sub validator($a0) {
+ my @a = sort @{$a0};
+ my $l = scalar @a;
+ if ($a[0] == 0 && $a[$l - 2] == 0 && $a[$l - 1] == 1) {
+ foreach my $i (0 .. $l - 1) {
+ if ($a0->[$i]== 1) {
+ return $i;
+ }
+ }
+ }
+ return -1;
+}
+
+sub specialpositions($a) {
+ my @vr = ();
+ my %xs = ();
+ while (my ($y, $row) = each @{$a}) {
+ my $x = validator($row);
+ if ($x > -1) {
+ push @vr, [$y, $x];
+ $xs{$x} = 1;
+ }
+ }
+ foreach my $x (keys %xs) {
+ keys @{$a};
+ my @c = (map {$_->[$x]} @{$a});
+ if (validator(\@c) == -1) {
+ delete $xs{$x};
+ }
+ }
+ return scalar grep {exists $xs{$_->[1]}} @vr;
+}
diff --git a/challenge-270/roger-bell-west/perl/ch-2.pl b/challenge-270/roger-bell-west/perl/ch-2.pl
new file mode 100755
index 0000000000..8f0d510e13
--- /dev/null
+++ b/challenge-270/roger-bell-west/perl/ch-2.pl
@@ -0,0 +1,41 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 2;
+
+is(equalizearray([4, 1], 3, 2), 9, 'example 1');
+is(equalizearray([2, 3, 3, 3, 5], 2, 1), 6, 'example 2');
+
+sub equalizearray($a0, $x, $y) {
+ my @a = sort @{$a0};
+ my $limit = $a[-1];
+ my @queue;
+ push @queue, [\@a, 0];
+ my $mc = -1;
+ while (scalar @queue > 0) {
+ my $op = shift @queue;
+ if ($mc == -1 || $mc > $op->[1]) {
+ if ($op->[0][0] == $op->[0][-1]) {
+ $mc = $op->[1];
+ } else {
+ my @p = @{$op->[0]};
+ $p[0]++;
+ if ($p[0] <= $limit) {
+ @p = sort @p;
+ push @queue,[ \@p, $op->[1] + $x];
+ my @q = @{$op->[0]};
+ $q[0]++;
+ $q[1]++;
+ if ($q[1] <= $limit) {
+ @q = sort @q;
+ push @queue,[ \@q, $op->[1] + $y];
+ }
+ }
+ }
+ }
+ }
+ return $mc;
+}
diff --git a/challenge-270/roger-bell-west/postscript/ch-1.ps b/challenge-270/roger-bell-west/postscript/ch-1.ps
new file mode 100644
index 0000000000..d3ff86afc6
--- /dev/null
+++ b/challenge-270/roger-bell-west/postscript/ch-1.ps
@@ -0,0 +1,248 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/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 {
+ /test.count test.count 1 add def
+ {
+ /test.pass test.pass 1 add def
+ } {
+ ( ) print
+ test.count (....) cvs print
+ (-fail) print
+ } ifelse
+} bind def
+
+/filter { % array proc(bool) -> array
+ 1 dict begin
+ /p exch def
+ [ exch
+ {
+ dup p not
+ {
+ pop
+ } if
+ } forall
+ ]
+ end
+} bind def
+
+/keys { % dict -> array of dict keys
+ [ exch
+ {
+ pop
+ } forall
+ ]
+} 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.cmp {
+ 2 copy
+ lt {
+ pop pop -1
+ } {
+ gt {
+ 1
+ } {
+ 0
+ } ifelse
+ } ifelse
+} 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
+
+/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
+
+/map { % array proc -> array
+ 2 dict begin
+ /p exch def
+ [ exch
+ {
+ p
+ } forall
+ ]
+ 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
+
+/enumerate.array {
+ 1 dict begin
+ /a exch def
+ [
+ 0 1 a length 1 sub {
+ [ exch dup a exch get ]
+ } for
+ ]
+ 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
+
+
+% end included library code
+
+/validator {
+ 0 dict begin
+ /a0 exch def
+ /a a0 deepcopy quicksort def
+ /l a length def
+ -1
+ a 0 get 0 eq a l 2 sub get 0 eq a l 1 sub get 1 eq and and {
+ 0 1 l 1 sub {
+ /i exch def
+ a0 i get 1 eq {
+ pop i
+ exit
+ } if
+ } for
+ } if
+ end
+} bind def
+
+/specialpositions {
+ 0 dict begin
+ /a exch def
+ /xs 0 dict def
+ /vr [
+ a enumerate.array {
+ aload pop
+ /row exch def
+ /y exch def
+ /x row validator def
+ x -1 gt {
+ xs x true put
+ [ y x ]
+ } if
+ } forall
+ ] def
+ xs keys {
+ /x exch def
+ a { x get } map validator -1 eq {
+ xs x undef
+ } if
+ } forall
+ vr { 1 get xs exch known } filter length
+ end
+} bind def
+
+(specialpositions) test.start
+[[1 0 0] [0 0 1] [1 0 0]] specialpositions 1 eq test
+[[1 0 0] [0 1 0] [0 0 1]] specialpositions 3 eq test
+test.end
diff --git a/challenge-270/roger-bell-west/postscript/ch-2.ps b/challenge-270/roger-bell-west/postscript/ch-2.ps
new file mode 100644
index 0000000000..910546e753
--- /dev/null
+++ b/challenge-270/roger-bell-west/postscript/ch-2.ps
@@ -0,0 +1,215 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/keys { % dict -> array of dict keys
+ [ exch
+ {
+ pop
+ } forall
+ ]
+} bind def
+
+/apop.left { % [a b c] -> [b c] a
+ dup 0 get exch
+ [ exch aload length -1 roll pop ] exch
+} bind def
+
+/test.start {
+ print (:) print
+ /test.pass 0 def
+ /test.count 0 def
+} 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 {
+ { quicksort.cmp } quicksort.with_comparator
+} 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 {
+ /test.count test.count 1 add def
+ {
+ /test.pass test.pass 1 add def
+ } {
+ ( ) print
+ test.count (....) cvs print
+ (-fail) print
+ } ifelse
+} 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.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
+
+/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
+
+/apush.right { % [a b] c -> [a b c]
+ exch
+ [ exch aload length 2 add -1 roll ]
+} bind def
+
+
+% end included library code
+
+/equalizearray {
+ 0 dict begin
+ /y exch def
+ /x exch def
+ /a exch quicksort def
+ /limit a dup length 1 sub get def
+ /queue [ [ a 0 ] ] def
+ /mc -1 def
+ {
+ queue length 1 ge {
+ queue apop.left /op exch def /queue exch def
+ mc -1 eq mc op 1 get gt or {
+ op 0 get 0 get op 0 get dup length 1 sub get eq {
+ /mc op 1 get def
+ } {
+ /p op 0 get deepcopy def
+ p 0 p 0 get 1 add put
+ p 0 get limit le {
+ /p p quicksort def
+ /queue queue [ p op 1 get x add ] apush.right def
+ /q op 0 get deepcopy def
+ q 0 q 0 get 1 add put
+ q 1 q 1 get 1 add put
+ q 1 get limit le {
+ /q q quicksort def
+ /queue queue [ q op 1 get y add ] apush.right def
+ } if
+ } if
+ } ifelse
+ } if
+ } {
+ exit
+ } ifelse
+ } loop
+ mc
+ end
+} bind def
+
+(equalizearray) test.start
+[4 1] 3 2 equalizearray 9 eq test
+[2 3 3 3 5] 2 1 equalizearray 6 eq test
+test.end
diff --git a/challenge-270/roger-bell-west/python/ch-1.py b/challenge-270/roger-bell-west/python/ch-1.py
new file mode 100755
index 0000000000..56c82863e0
--- /dev/null
+++ b/challenge-270/roger-bell-west/python/ch-1.py
@@ -0,0 +1,37 @@
+#! /usr/bin/python3