aboutsummaryrefslogtreecommitdiff
path: root/challenge-294
diff options
context:
space:
mode:
authorRoger Bell_West <roger@firedrake.org>2024-11-05 12:07:14 +0000
committerRoger Bell_West <roger@firedrake.org>2024-11-05 12:07:14 +0000
commitb42c2bcd51978e5617e2e4b7da4c9c7eac723270 (patch)
tree3398119cd119cb9142ce85f15041b4d78c6f2f3f /challenge-294
parent3e3453d23c7de1c054de694f4a3dbe86599d038b (diff)
downloadperlweeklychallenge-club-b42c2bcd51978e5617e2e4b7da4c9c7eac723270.tar.gz
perlweeklychallenge-club-b42c2bcd51978e5617e2e4b7da4c9c7eac723270.tar.bz2
perlweeklychallenge-club-b42c2bcd51978e5617e2e4b7da4c9c7eac723270.zip
RogerBW solutions for challenge no. 294
Diffstat (limited to 'challenge-294')
-rwxr-xr-xchallenge-294/roger-bell-west/crystal/ch-1.cr48
-rwxr-xr-xchallenge-294/roger-bell-west/crystal/ch-2.cr33
-rwxr-xr-xchallenge-294/roger-bell-west/javascript/ch-1.js58
-rwxr-xr-xchallenge-294/roger-bell-west/javascript/ch-2.js125
-rw-r--r--challenge-294/roger-bell-west/kotlin/ch-1.kt55
-rw-r--r--challenge-294/roger-bell-west/kotlin/ch-2.kt107
-rwxr-xr-xchallenge-294/roger-bell-west/lua/ch-1.lua67
-rwxr-xr-xchallenge-294/roger-bell-west/lua/ch-2.lua131
-rwxr-xr-xchallenge-294/roger-bell-west/perl/ch-1.pl40
-rwxr-xr-xchallenge-294/roger-bell-west/perl/ch-2.pl35
-rw-r--r--challenge-294/roger-bell-west/postscript/ch-1.ps161
-rw-r--r--challenge-294/roger-bell-west/postscript/ch-2.ps304
-rwxr-xr-xchallenge-294/roger-bell-west/python/ch-1.py41
-rwxr-xr-xchallenge-294/roger-bell-west/python/ch-2.py33
-rwxr-xr-xchallenge-294/roger-bell-west/raku/ch-1.p636
-rwxr-xr-xchallenge-294/roger-bell-west/raku/ch-2.p628
-rwxr-xr-xchallenge-294/roger-bell-west/ruby/ch-1.rb52
-rwxr-xr-xchallenge-294/roger-bell-west/ruby/ch-2.rb38
-rwxr-xr-xchallenge-294/roger-bell-west/rust/ch-1.rs51
-rwxr-xr-xchallenge-294/roger-bell-west/rust/ch-2.rs37
-rw-r--r--challenge-294/roger-bell-west/scala/ch-1.scala58
-rw-r--r--challenge-294/roger-bell-west/scala/ch-2.scala102
-rw-r--r--challenge-294/roger-bell-west/tests.json32
23 files changed, 1672 insertions, 0 deletions
diff --git a/challenge-294/roger-bell-west/crystal/ch-1.cr b/challenge-294/roger-bell-west/crystal/ch-1.cr
new file mode 100755
index 0000000000..edb64abd9a
--- /dev/null
+++ b/challenge-294/roger-bell-west/crystal/ch-1.cr
@@ -0,0 +1,48 @@
+#! /usr/bin/crystal
+
+
+def consecutivesequence(a)
+ b = a.sort
+ mxlen = 0
+ here = 0
+ while true
+ (here + 1).upto(b.size - 1) do |there|
+ if b[there] != there - here + b[here]
+ l = there - here
+ if l > mxlen
+ mxlen = l
+ end
+ here = there
+ break
+ end
+ if there == b.size - 1
+ l = there - here + 1
+ if l > mxlen
+ mxlen = l
+ end
+ here = there
+ break
+ end
+ end
+ if here >= b.size - 1
+ break
+ end
+ end
+ if mxlen < 2
+ mxlen = -1
+ end
+ mxlen
+end
+
+require "spec"
+describe "consecutivesequence" do
+ it "test_ex1" do
+ consecutivesequence([10, 4, 20, 1, 3, 2]).should eq 4
+ end
+ it "test_ex2" do
+ consecutivesequence([0, 6, 1, 8, 5, 2, 4, 3, 0, 7]).should eq 9
+ end
+ it "test_ex3" do
+ consecutivesequence([10, 30, 20]).should eq -1
+ end
+end
diff --git a/challenge-294/roger-bell-west/crystal/ch-2.cr b/challenge-294/roger-bell-west/crystal/ch-2.cr
new file mode 100755
index 0000000000..af1f265cea
--- /dev/null
+++ b/challenge-294/roger-bell-west/crystal/ch-2.cr
@@ -0,0 +1,33 @@
+#! /usr/bin/crystal
+
+def nextpermutation(a)
+ b = a.sort
+ flag = false
+ out = [] of Int32
+ b.permutations.each do |px|
+ if out.size == 0
+ out = px
+ end
+ if flag
+ out= px
+ break
+ end
+ if px == a
+ flag = true
+ end
+ end
+ out
+end
+
+require "spec"
+describe "nextpermutation" do
+ it "test_ex1" do
+ nextpermutation([1, 2, 3]).should eq [1, 3, 2]
+ end
+ it "test_ex2" do
+ nextpermutation([2, 1, 3]).should eq [2, 3, 1]
+ end
+ it "test_ex3" do
+ nextpermutation([3, 1, 2]).should eq [3, 2, 1]
+ end
+end
diff --git a/challenge-294/roger-bell-west/javascript/ch-1.js b/challenge-294/roger-bell-west/javascript/ch-1.js
new file mode 100755
index 0000000000..c8932a7825
--- /dev/null
+++ b/challenge-294/roger-bell-west/javascript/ch-1.js
@@ -0,0 +1,58 @@
+#! /usr/bin/node
+
+"use strict"
+
+function consecutivesequence(a){
+ let b = [...a];
+ b.sort(function(aa, bb) {
+ return aa - bb;
+ });
+ let mxlen = 0;
+ let here = 0;
+ while (true) {
+ for (let there = here + 1; there <= b.length - 1; there++) {
+ if (b[there] != there - here + b[here]) {
+ const l = there - here;
+ if (l > mxlen) {
+ mxlen = l;
+ }
+ here = there;
+ break;
+ }
+ if (there == b.length - 1) {
+ const l = there - here + 1;
+ if (l > mxlen) {
+ mxlen = l;
+ }
+ here = there;
+ break;
+ }
+ }
+ if (here >= b.length - 1) {
+ break;
+ }
+ }
+ if (mxlen < 2) {
+ mxlen = -1;
+ }
+ return mxlen;
+}
+
+if (consecutivesequence([10, 4, 20, 1, 3, 2]) == 4) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (consecutivesequence([0, 6, 1, 8, 5, 2, 4, 3, 0, 7]) == 9) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (consecutivesequence([10, 30, 20]) == -1) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-294/roger-bell-west/javascript/ch-2.js b/challenge-294/roger-bell-west/javascript/ch-2.js
new file mode 100755
index 0000000000..7a699e38a2
--- /dev/null
+++ b/challenge-294/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 permute(a) {
+ let out = [];
+ let n=a.length;
+ let c=[];
+ for (let i = 0; i < n; i++) {
+ c.push(0);
+ }
+ out.push([...a]);
+ let i=0;
+ while (true) {
+ if (i >= n) {
+ break;
+ }
+ if (c[i] < i) {
+ if (i % 2 == 0) {
+ [a[0],a[i]] = [a[i],a[0]];
+ } else {
+ [a[c[i]],a[i]] = [a[i],a[c[i]]];
+ }
+ out.push([...a]);
+ c[i]++;
+ i=0;
+ } else {
+ c[i]=0;
+ i++;
+ }
+ }
+ return out;
+}
+
+function nextpermutation(a) {
+ let b = [...a];
+ b.sort(function(aa, bb) {
+ return aa - bb;
+ });
+ let flag = false;
+ let out = [];
+ let pp = permute(b);
+ pp.sort(function(i, j) {
+ let ix = 0;
+ let res = 1;
+ while (true) {
+ if (ix >= i.length && ix >= j.length) {
+ break;
+ }
+ if (ix < i.length && ix >= j.length) {
+ res = 1;
+ break;
+ }
+ if (ix >= i.length && ix < j.length) {
+ res = -1;
+ break;
+ }
+ if (i[ix] != j[ix]) {
+ res = i[ix] - j[ix];
+ break;
+ }
+ ix++;
+ }
+ return res
+ });
+ for (let px of pp) {
+ if (out.length == 1) {
+ out = px;
+ }
+ if (flag) {
+ out = px
+ flag = false;
+ }
+ if (deepEqual(px, a)) {
+ flag = true;
+ }
+ }
+ return out
+}
+
+if (deepEqual(nextpermutation([1, 2, 3]), [1, 3, 2])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(nextpermutation([2, 1, 3]), [2, 3, 1])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(nextpermutation([3, 1, 2]), [3, 2, 1])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-294/roger-bell-west/kotlin/ch-1.kt b/challenge-294/roger-bell-west/kotlin/ch-1.kt
new file mode 100644
index 0000000000..e07b9cde63
--- /dev/null
+++ b/challenge-294/roger-bell-west/kotlin/ch-1.kt
@@ -0,0 +1,55 @@
+fun consecutivesequence(a: List<Int>): Int {
+ val b = a.sorted()
+ var mxlen = 0
+ var here = 0
+ while (true) {
+ for (there in here + 1 .. b.size - 1) {
+ if (b[there] != there - here + b[here]) {
+ val l = there - here
+ if (l > mxlen) {
+ mxlen = l
+ }
+ here = there
+ break
+ }
+ if (there == b.size - 1) {
+ val l = there - here + 1
+ if (l > mxlen) {
+ mxlen = l
+ }
+ here = there
+ break
+ }
+ }
+ if (here >= b.size - 1) {
+ break
+ }
+ }
+ if (mxlen < 2) {
+ mxlen = -1
+ }
+ return mxlen
+}
+
+fun main() {
+
+ if (consecutivesequence(listOf(10, 4, 20, 1, 3, 2)) == 4) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (consecutivesequence(listOf(0, 6, 1, 8, 5, 2, 4, 3, 0, 7)) == 9) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (consecutivesequence(listOf(10, 30, 20)) == -1) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-294/roger-bell-west/kotlin/ch-2.kt b/challenge-294/roger-bell-west/kotlin/ch-2.kt
new file mode 100644
index 0000000000..99d6b20d35
--- /dev/null
+++ b/challenge-294/roger-bell-west/kotlin/ch-2.kt
@@ -0,0 +1,107 @@
+fun permute(aa: List<Int>): ArrayList<List<Int>> {
+ var a = ArrayList<Int>()
+ for (i in aa) {
+ a.add(i)
+ }
+ var out = ArrayList<List<Int>>()
+ val n = a.size
+ var c = ArrayList<Int>();
+ for (i in 0..n-1) {
+ c.add(0)
+ }
+ out.add(a.toList())
+ var i = 0
+ while (true) {
+ if (i >= n) {
+ break
+ }
+ if (c[i] < i) {
+ if (i % 2 == 0) {
+ val tmp = a[0]
+ a[0] = a[i]
+ a[i] = tmp
+ } else {
+ val tmp = a[c[i]]
+ a[c[i]] = a[i]
+ a[i] = tmp
+ }
+ out.add(a.toList())
+ c[i] += 1
+ i = 0
+ } else {
+ c[i] = 0
+ i += 1
+ }
+ }
+ return out
+}
+
+fun nextpermutation(a: List<Int>): List<Int> {
+ val b = a.sorted()
+ var flag = false
+ var out = listOf(0)
+ val listComparator = Comparator {
+ i: List<Int>, j: List<Int> ->
+ var ix = 0
+ var res = false
+ while (true) {
+ if (ix >= i.size && ix >= j.size) {
+ break
+ }
+ if (ix < i.size && ix >= j.size) {
+ res = true
+ break
+ }
+ if (ix >= i.size && ix < j.size) {
+ res = false
+ break
+ }
+ if (i[ix] != j[ix]) {
+ res = i[ix] < j[ix]
+ break
+ }
+ ix += 1
+ }
+ if (res) {
+ -1
+ } else {
+ 1
+ }
+ }
+ for (px in permute(b).sortedWith(listComparator)) {
+ if (out.size == 1) {
+ out = px
+ }
+ if (flag) {
+ out = px
+ flag = false
+ }
+ if (px == a) {
+ flag = true
+ }
+ }
+ return out
+}
+
+ fun main() {
+
+ if (nextpermutation(listOf(1, 2, 3)) == listOf(1, 3, 2)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (nextpermutation(listOf(2, 1, 3)) == listOf(2, 3, 1)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (nextpermutation(listOf(3, 1, 2)) == listOf(3, 2, 1)) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-294/roger-bell-west/lua/ch-1.lua b/challenge-294/roger-bell-west/lua/ch-1.lua
new file mode 100755
index 0000000000..605d27309d
--- /dev/null
+++ b/challenge-294/roger-bell-west/lua/ch-1.lua
@@ -0,0 +1,67 @@
+#! /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 consecutivesequence(a)
+ local b = deepcopy(a)
+ table.sort(b)
+ local mxlen = 0
+ local here = 1
+ while true do
+ for there = here + 1, #b do
+ if b[there] ~= there - here + b[here] then
+ local l = there - here
+ if l > mxlen then
+ mxlen = l
+ end
+ here = there
+ break
+ end
+ if there == #b then
+ local l = there - here + 1
+ if l > mxlen then
+ mxlen = l
+ end
+ here = there
+ break
+ end
+ end
+ if here >= #b then
+ break
+ end
+ end
+ if mxlen < 2 then
+ mxlen = -1
+ end
+ return mxlen
+end
+
+if consecutivesequence({10, 4, 20, 1, 3, 2}) == 4 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if consecutivesequence({0, 6, 1, 8, 5, 2, 4, 3, 0, 7}) == 9 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if consecutivesequence({10, 30, 20}) == -1 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-294/roger-bell-west/lua/ch-2.lua b/challenge-294/roger-bell-west/lua/ch-2.lua
new file mode 100755
index 0000000000..a96ec89499
--- /dev/null
+++ b/challenge-294/roger-bell-west/lua/ch-2.lua
@@ -0,0 +1,131 @@
+#! /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 permute(a)
+ local out = {}
+ local n = #a
+ local c = {}
+ for i = 1,n do
+ table.insert(c, 1)
+ end
+ table.insert(out, deepcopy(a))
+ local i=1
+ while true do
+ if i > n then
+ break
+ end
+ if c[i] < i then
+ if i % 2 == 1 then
+ a[1],a[i] = a[i],a[1]
+ else
+ a[c[i]],a[i] = a[i],a[c[i]]
+ end
+ table.insert(out, deepcopy(a))
+ c[i] = c[i]+1
+ i = 1
+ else
+ c[i] = 1
+ i = i+1
+ end
+ end
+ return out
+end
+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 listcmp(a, b)
+ local ix = 1
+ while true do
+ if ix > #a and ix > #b then
+ return false
+ end
+ if ix <= #a and ix > #b then
+ return true
+ end
+ if ix > #a and ix <= #b then
+ return false
+ end
+ if a[ix] ~= b[ix] then
+ return a[ix] < b[ix]
+ end
+ ix = ix + 1
+ end
+end
+
+function nextpermutation(a)
+ local b = deepcopy(a)
+ table.sort(b)
+ local flag = false
+ local out = {}
+ local pp = permute(b)
+ table.sort(pp, listcmp)
+ for _, px in ipairs(pp) do
+ if #out == 0 then
+ out = px
+ end
+ if flag then
+ out = px
+ end
+ if recursive_compare(px, a) then
+ flag = true
+ end
+ end
+ return out
+end
+
+if recursive_compare(nextpermutation({1, 2, 3}), {1, 3, 2}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(nextpermutation({2, 1, 3}), {2, 3, 1}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(nextpermutation({3, 1, 2}), {3, 2, 1}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-294/roger-bell-west/perl/ch-1.pl b/challenge-294/roger-bell-west/perl/ch-1.pl
new file mode 100755
index 0000000000..be1285a416
--- /dev/null
+++ b/challenge-294/roger-bell-west/perl/ch-1.pl
@@ -0,0 +1,40 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 3;
+
+is(consecutivesequence([10, 4, 20, 1, 3, 2]), 4, 'example 1');
+is(consecutivesequence([0, 6, 1, 8, 5, 2, 4, 3, 0, 7]), 9, 'example 2');
+is(consecutivesequence([10, 30, 20]), -1, 'example 3');
+
+use List::Util qw(max);
+
+sub consecutivesequence($a) {
+ my @b = sort {$::a <=> $::b} @{$a};
+ my $mxlen = 0;
+ my $here = 0;
+ while (1) {
+ foreach my $there (($here + 1) .. $#b) {
+ if ($b[$there] != $there - $here + $b[$here]) {
+ $mxlen = max($mxlen, $there - $here);
+ $here = $there;
+ last;
+ }
+ if ($there == $#b) {
+ $mxlen = max($mxlen, $there - $here + 1);
+ $here = $there;
+ last;
+ }
+ }
+ if ($here >= $#b) {
+ last;
+ }
+ }
+ if ($mxlen < 2) {
+ $mxlen = -1;
+ }
+ $mxlen;
+}
diff --git a/challenge-294/roger-bell-west/perl/ch-2.pl b/challenge-294/roger-bell-west/perl/ch-2.pl
new file mode 100755
index 0000000000..a78ea2fbc2
--- /dev/null
+++ b/challenge-294/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 => 3;
+
+is_deeply(nextpermutation([1, 2, 3]), [1, 3, 2], 'example 1');
+is_deeply(nextpermutation([2, 1, 3]), [2, 3, 1], 'example 2');
+is_deeply(nextpermutation([3, 1, 2]), [3, 2, 1], 'example 3');
+
+use Algorithm::Combinatorics qw(permutations);
+use Array::Compare;
+
+sub nextpermutation($a) {
+ my @b = sort {$::a <=> $::b} @{$a};
+ my $flag = 0;
+ my @out;
+ my $comp = Array::Compare->new;
+ my $ip = permutations(\@b);
+ while (my $px = $ip->next) {
+ if (scalar @out == 0) {
+ @out = @{$px};
+ }
+ if ($flag) {
+ @out = @{$px};
+ last;
+ }
+ if ($comp->compare($px, $a)) {
+ $flag = 1;
+ }
+ }
+ \@out;
+}
diff --git a/challenge-294/roger-bell-west/postscript/ch-1.ps b/challenge-294/roger-bell-west/postscript/ch-1.ps
new file mode 100644
index 0000000000..67eeff8eb6
--- /dev/null
+++ b/challenge-294/roger-bell-west/postscript/ch-1.ps
@@ -0,0 +1,161 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/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
+
+/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
+
+/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.cmp {
+ 2 copy
+ lt {
+ pop pop -1
+ } {
+ gt {
+ 1
+ } {
+ 0
+ } ifelse
+ } 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 {
+ { 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
+
+
+% end included library code
+
+/consecutivesequence {
+ 0 dict begin
+ quicksort /b exch def
+ /mxlen 0 def
+ /here 0 def
+ {
+ here 1 add 1 b length 1 sub {
+ /there exch def
+ b there get there here sub b here get add ne {
+ /mxlen mxlen there here sub max def
+ /here there def
+ exit
+ } if
+ there b length 1 sub eq {
+ /mxlen mxlen there here sub 1 add max def
+ /here there def
+ exit
+ } if
+ } for
+ here b length 1 sub ge {
+ exit
+ } if
+ } loop
+ mxlen 2 lt {
+ /mxlen -1 def
+ } if
+ mxlen
+ end
+} bind def
+
+(consecutivesequence) test.start
+[10 4 20 1 3 2] consecutivesequence 4 eq test
+[0 6 1 8 5 2 4 3 0 7] consecutivesequence 9 eq test
+[10 30 20] consecutivesequence -1 eq test
+test.end
diff --git a/challenge-294/roger-bell-west/postscript/ch-2.ps b/challenge-294/roger-bell-west/postscript/ch-2.ps
new file mode 100644
index 0000000000..4a4ddaa659
--- /dev/null
+++ b/challenge-294/roger-bell-west/postscript/ch-2.ps
@@ -0,0 +1,304 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/quicksort.with_keygen { % [ a c b ] { keygen } -> [ a b c ]
+ 3 dict begin
+ /kg exch def
+ /arr exch def
+ /kl << arr {
+ dup kg
+ } forall >> def
+ arr {
+ exch kl exch get exch kl exch get 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
+
+/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
+
+/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
+
+/quicksort {
+ { quicksort.cmp } quicksort.with_comparator
+} bind def
+
+/permute.swap {
+ /permute.bi exch def
+ /permute.ai exch def
+ permute.a permute.ai get
+ permute.a permute.bi get
+ permute.a exch permute.ai exch put
+ permute.a exch permute.bi exch put
+} 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
+<