aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2022-04-05 13:19:10 +0100
committerGitHub <noreply@github.com>2022-04-05 13:19:10 +0100
commitaca07baa407db3262c60483587a3924c33faa370 (patch)
tree13d4c8046c1ba2456a6242dcf7921cffd7e9c953
parent21b2771f7439710ee9a4631c40679a916ca9f723 (diff)
parent13809215bbd6899853b500386805feffe995bbe4 (diff)
downloadperlweeklychallenge-club-aca07baa407db3262c60483587a3924c33faa370.tar.gz
perlweeklychallenge-club-aca07baa407db3262c60483587a3924c33faa370.tar.bz2
perlweeklychallenge-club-aca07baa407db3262c60483587a3924c33faa370.zip
Merge pull request #5883 from Firedrake/rogerbw-challenge-159
Solutions for challenge #159
-rwxr-xr-xchallenge-159/roger-bell-west/javascript/ch-1.js97
-rwxr-xr-xchallenge-159/roger-bell-west/javascript/ch-2.js94
-rw-r--r--challenge-159/roger-bell-west/kotlin/ch-1.kt72
-rw-r--r--challenge-159/roger-bell-west/kotlin/ch-2.kt94
-rwxr-xr-xchallenge-159/roger-bell-west/lua/ch-1.lua104
-rwxr-xr-xchallenge-159/roger-bell-west/lua/ch-2.lua97
-rwxr-xr-xchallenge-159/roger-bell-west/perl/ch-1.pl56
-rwxr-xr-xchallenge-159/roger-bell-west/perl/ch-2.pl78
-rw-r--r--challenge-159/roger-bell-west/postscript/ch-1.ps256
-rw-r--r--challenge-159/roger-bell-west/postscript/ch-2.ps217
-rwxr-xr-xchallenge-159/roger-bell-west/python/ch-1.py50
-rwxr-xr-xchallenge-159/roger-bell-west/python/ch-2.py75
-rwxr-xr-xchallenge-159/roger-bell-west/raku/ch-1.p651
-rwxr-xr-xchallenge-159/roger-bell-west/raku/ch-2.p674
-rwxr-xr-xchallenge-159/roger-bell-west/ruby/ch-1.rb52
-rwxr-xr-xchallenge-159/roger-bell-west/ruby/ch-2.rb36
-rwxr-xr-xchallenge-159/roger-bell-west/rust/ch-1.rs97
-rwxr-xr-xchallenge-159/roger-bell-west/rust/ch-2.rs84
18 files changed, 1684 insertions, 0 deletions
diff --git a/challenge-159/roger-bell-west/javascript/ch-1.js b/challenge-159/roger-bell-west/javascript/ch-1.js
new file mode 100755
index 0000000000..c18b03883d
--- /dev/null
+++ b/challenge-159/roger-bell-west/javascript/ch-1.js
@@ -0,0 +1,97 @@
+#! /usr/bin/node
+
+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 gcd (m0,n0) {
+ let m=m0
+ let n=n0
+ while (n != 0) {
+ [m,n]=[n,m % n]
+ }
+ return m
+}
+
+function lcm (m,n) {
+ return m/gcd(m,n)*n
+}
+
+function lcmseries(a0,b) {
+ let a=a0
+ for (let i=a+1;i <= b;i++) {
+ a=lcm(a,i)
+ }
+ return a
+}
+
+function farey (n) {
+ let l=lcmseries(2,n)
+ let d=new Map()
+ let s=[]
+ for (let i=1;i <= n;i++) {
+ let m=l/i
+ for (let j=0;j <= i;j++) {
+ let k=m*j
+ if (!d.has(k)) {
+ d.set(k,[j,i])
+ s.push(k)
+ }
+ }
+ }
+ s.sort(function(a,b) {
+ return a-b;
+ })
+ return s.map(i => d.get(i))
+}
+
+if (deepEqual(farey(5),[
+ [0, 1], [1, 5], [1, 4], [1, 3], [2, 5], [1, 2], [3, 5], [2, 3],
+ [3, 4], [4, 5], [1, 1]
+])) {
+ process.stdout.write("Pass")
+} else {
+ process.stdout.write("FAIL")
+}
+process.stdout.write(" ");
+
+if (deepEqual(farey(7),[
+ [0, 1], [1, 7], [1, 6], [1, 5], [1, 4], [2, 7], [1, 3], [2, 5],
+ [3, 7], [1, 2], [4, 7], [3, 5], [2, 3], [5, 7], [3, 4], [4, 5],
+ [5, 6], [6, 7], [1, 1]
+])) {
+ process.stdout.write("Pass")
+} else {
+ process.stdout.write("FAIL")
+}
+process.stdout.write(" ");
+
+if (deepEqual(farey(4),[
+ [0, 1], [1, 4], [1, 3], [1, 2], [2, 3], [3, 4], [1, 1]
+])) {
+ process.stdout.write("Pass")
+} else {
+ process.stdout.write("FAIL")
+}
+process.stdout.write("\n");
diff --git a/challenge-159/roger-bell-west/javascript/ch-2.js b/challenge-159/roger-bell-west/javascript/ch-2.js
new file mode 100755
index 0000000000..619b239213
--- /dev/null
+++ b/challenge-159/roger-bell-west/javascript/ch-2.js
@@ -0,0 +1,94 @@
+#! /usr/bin/node
+
+function genprimes(mx) {
+ let primesh=new Set([2,3])
+ for (let i = 6; i <= mx; i += 6) {
+ for (let j = i-1; j <= i+1; j += 2) {
+ if (j <= mx) {
+ primesh.add(j);
+ }
+ }
+ }
+ let q=[2,3,5,7];
+ let p=q.shift();
+ let mr=Math.floor(Math.sqrt(mx));
+ while (p <= mr) {
+ if (primesh.has(p)) {
+ let i=p*p
+ for (let i=p*p; i <= mx; i += p) {
+ primesh.delete(i);
+ }
+ }
+ if (q.length < 2) {
+ q.push(q[q.length-1]+4);
+ q.push(q[q.length-1]+2);
+ }
+ p=q.shift();
+ }
+ let primes=[...primesh];
+ primes.sort(function(a,b) {
+ return a-b;
+ });
+ return primes;
+}
+
+function primefactor (n) {
+ let f=new Map()
+ let m=n
+ for (let p of genprimes(Math.floor(Math.sqrt(n)))) {
+ while (m % p == 0) {
+ m=Math.floor(m/p)
+ if (f.has(p)) {
+ f.set(p,f.get(p)+1)
+ } else {
+ f.set(p,1)
+ }
+ if (m == 1) {
+ break
+ }
+ }
+ }
+ if (m > 1) {
+ if (f.has(m)) {
+ f.set(m,f.get(m)+1)
+ } else {
+ f.set(m,1)
+ }
+ }
+ return f
+}
+
+function moebius (n) {
+ let z=0
+ for (let v of primefactor(n).values()) {
+ if (v > 1) {
+ return 0
+ }
+ z++
+ }
+ if (z % 2 == 0) {
+ return 1
+ }
+ return -1
+}
+
+if (moebius(5) == -1) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+
+if (moebius(10) == 1) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+
+if (moebius(20) == 0) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-159/roger-bell-west/kotlin/ch-1.kt b/challenge-159/roger-bell-west/kotlin/ch-1.kt
new file mode 100644
index 0000000000..362aa1c7f6
--- /dev/null
+++ b/challenge-159/roger-bell-west/kotlin/ch-1.kt
@@ -0,0 +1,72 @@
+import kotlin.math.*
+
+fun gcd(m0: Int,n0: Int): Int {
+ var m=m0
+ var n=n0
+ while (n != 0) {
+ val tmp=m % n
+ m = n
+ n = tmp
+ }
+ return m
+}
+
+fun lcm(m: Int,n: Int): Int {
+ return m/gcd(m,n)*n
+}
+
+fun lcmseries(s: List<Int>): Int {
+ return s.reduce { acc, x -> lcm(acc,x) }
+}
+
+fun farey(n: Int): List<Pair<Int,Int>> {
+ val l = lcmseries((2..n).toList())
+ var d = mutableMapOf<Int,Pair<Int,Int>>()
+ var s = ArrayList<Int>()
+ for (i in 1..n) {
+ val m = l / i
+ for (j in 0..i) {
+ val k = m * j
+ if (!d.contains(k)) {
+ d[k]=Pair(j,i)
+ s.add(k)
+ }
+ }
+ }
+ s.sort()
+ return s.map {d[it]!!}
+}
+
+fun main() {
+ if (farey(5) == listOf(
+ Pair(0, 1), Pair(1, 5), Pair(1, 4), Pair(1, 3),
+ Pair(2, 5), Pair(1, 2), Pair(3, 5), Pair(2, 3),
+ Pair(3, 4), Pair(4, 5), Pair(1, 1)
+ )) {
+ print("Pass")
+ } else {
+ print("FAIL")
+ }
+ print(" ")
+ if (farey(7) == listOf(
+ Pair(0, 1), Pair(1, 7), Pair(1, 6), Pair(1, 5),
+ Pair(1, 4), Pair(2, 7), Pair(1, 3), Pair(2, 5),
+ Pair(3, 7), Pair(1, 2), Pair(4, 7), Pair(3, 5),
+ Pair(2, 3), Pair(5, 7), Pair(3, 4), Pair(4, 5),
+ Pair(5, 6), Pair(6, 7), Pair(1, 1)
+ )) {
+ print("Pass")
+ } else {
+ print("FAIL")
+ }
+ print(" ")
+ if (farey(4) == listOf(
+ Pair(0, 1), Pair(1, 4), Pair(1, 3), Pair(1, 2),
+ Pair(2, 3), Pair(3, 4), Pair(1, 1)
+ )) {
+ print("Pass")
+ } else {
+ print("FAIL")
+ }
+ println("")
+}
diff --git a/challenge-159/roger-bell-west/kotlin/ch-2.kt b/challenge-159/roger-bell-west/kotlin/ch-2.kt
new file mode 100644
index 0000000000..8cbe15e254
--- /dev/null
+++ b/challenge-159/roger-bell-west/kotlin/ch-2.kt
@@ -0,0 +1,94 @@
+import kotlin.math.*
+
+fun genprimes(mx: Int): ArrayList<Int> {
+ var primesh=mutableSetOf<Int>()
+ for (i in 2..3) {
+ primesh.add(i)
+ }
+ for (i in 6..mx+1 step 6) {
+ for (j in i-1..i+1 step 2) {
+ if (j <= mx) {
+ primesh.add(j)
+ }
+ }
+ }
+ var q=ArrayDeque(listOf(2,3,5,7))
+ var p=q.removeFirst()
+ val mr=sqrt(mx.toDouble()).toInt()
+ while (p <= mr) {
+ if (primesh.contains(p)) {
+ for (i in p*p..mx step p) {
+ primesh.remove(i)
+ }
+ }
+ if (q.size < 2) {
+ q.add(q.last()+4)
+ q.add(q.last()+2)
+ }
+ p=q.removeFirst()
+ }
+ var primes=ArrayList(primesh.distinct())
+ primes.sort()
+ return primes
+}
+
+fun primefactor(n: Int): Map<Int,Int> {
+ var f=mutableMapOf<Int,Int>()
+ var m=n
+ for (p in genprimes(sqrt(m.toDouble()).toInt())) {
+ while (m % p == 0) {
+ m /= p
+ if (f.containsKey(p)) {
+ f[p] = f[p]!!+1
+ } else {
+ f[p]=1
+ }
+ }
+ if (m == 1) {
+ break
+ }
+ }
+ if (m > 1) {
+ if (f.containsKey(m)) {
+ f[m] = f[m]!!+1
+ } else {
+ f[m]=1
+ }
+ }
+ return f
+}
+
+fun moebius(n: Int): Int {
+ var z: Int=0
+ for (v in primefactor(n).values) {
+ if (v > 1) {
+ return 0
+ }
+ z += 1
+ }
+ if (z % 2 == 0) {
+ return 1
+ }
+ return -1
+}
+
+fun main() {
+ if (moebius(5) == -1) {
+ print("Pass")
+ } else {
+ print("FAIL")
+ }
+ print(" ")
+ if (moebius(10) == 1) {
+ print("Pass")
+ } else {
+ print("FAIL")
+ }
+ print(" ")
+ if (moebius(20) == 0) {
+ print("Pass")
+ } else {
+ print("FAIL")
+ }
+ println("")
+}
diff --git a/challenge-159/roger-bell-west/lua/ch-1.lua b/challenge-159/roger-bell-west/lua/ch-1.lua
new file mode 100755
index 0000000000..d10299f584
--- /dev/null
+++ b/challenge-159/roger-bell-west/lua/ch-1.lua
@@ -0,0 +1,104 @@
+#! /usr/bin/lua
+
+-- by Michael Anderson at
+-- https://stackoverflow.com/questions/8722620/comparing-two-index-tables-by-index-value-in-lua
+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
+
+ -- Check each key-value pair
+ -- We have to do this both ways in case we miss some.
+ -- TODO: Could probably be smarter and not check those we've
+ -- already checked though!
+ for k1,v1 in pairs(t1) do
+ local v2 = t2[k1]
+ if( not recursive_compare(v1,v2) ) then return false end
+ end
+ for k2,v2 in pairs(t2) do
+ local v1 = t1[k2]
+ if( not recursive_compare(v1,v2) ) then return false end
+ end
+
+ return true
+end
+
+function gcd(m0,n0)
+ local m,n = m0,n0
+ while n ~= 0 do
+ m,n = n,m % n
+ end
+ return m
+end
+
+function lcm(m,n)
+ return m/gcd(m,n)*n
+end
+
+function lcmseries(a,b)
+ local t=1
+ for v = a,b do
+ t = lcm(t,v)
+ end
+ return t
+end
+
+function farey(n)
+ local l=lcmseries(2,n)
+ local d={}
+ local s={}
+ for i = 1,n do
+ local m = l / i
+ for j = 0,i do
+ local k = m * j
+ if d[k] == nil then
+ d[k] = {j,i}
+ table.insert(s,k)
+ end
+ end
+ end
+ table.sort(s)
+ local out={}
+ for k,v in ipairs(s) do
+ table.insert(out,d[v])
+ end
+ return out
+end
+
+if recursive_compare(farey(5),{
+ {0, 1}, {1, 5}, {1, 4}, {1, 3}, {2, 5},
+ {1, 2}, {3, 5}, {2, 3}, {3, 4}, {4, 5},
+ {1, 1}
+ }) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(farey(7),{
+ {0, 1}, {1, 7}, {1, 6}, {1, 5}, {1, 4},
+ {2, 7}, {1, 3}, {2, 5}, {3, 7}, {1, 2},
+ {4, 7}, {3, 5}, {2, 3}, {5, 7}, {3, 4},
+ {4, 5}, {5, 6}, {6, 7}, {1, 1}
+ }) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(farey(4),{
+ {0, 1}, {1, 4}, {1, 3}, {1, 2}, {2, 3},
+ {3, 4}, {1, 1}
+ }) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
diff --git a/challenge-159/roger-bell-west/lua/ch-2.lua b/challenge-159/roger-bell-west/lua/ch-2.lua
new file mode 100755
index 0000000000..1e79067d53
--- /dev/null
+++ b/challenge-159/roger-bell-west/lua/ch-2.lua
@@ -0,0 +1,97 @@
+#! /usr/bin/lua
+
+function genprimes(mx)
+ local primesh = {}
+ for i = 2, 3 do
+ primesh[i] = true
+ end
+ for i = 6, mx, 6 do
+ for j = i-1, i+1, 2 do
+ if j <= mx then
+ primesh[j]=true
+ end
+ end
+ end
+ local q={2,3,5,7}
+ local p=table.remove(q,1)
+ local mr=math.floor(math.sqrt(mx))
+ while p <= mr do
+ if primesh[p] ~= nil then
+ for i = p*p,mx,p do
+ primesh[i] = nil
+ end
+ end
+ if #q < 2 then
+ table.insert(q,q[#q]+4)
+ table.insert(q,q[#q]+2)
+ end
+ p=table.remove(q,1)
+ end
+ local primes = {}
+ for k,v in pairs(primesh) do
+ table.insert(primes,k)
+ end
+ table.sort(primes)
+ return primes
+end
+
+function primefactor(n)
+ local f={}
+ local m=n
+ for k,p in pairs(genprimes(math.floor(math.sqrt(m)))) do
+ while m % p == 0 do
+ m=math.floor(m/p)
+ if f[p] == nil then
+ f[p]=1
+ else
+ f[p] = f[p] + 1
+ end
+ if m==1 then
+ break
+ end
+ end
+ end
+ if m>1 then
+ if f[m] == nil then
+ f[m]=1
+ else
+ f[m] = f[m] + 1
+ end
+ end
+ return f
+end
+
+function moebius(n)
+ local z=0
+ for k,v in pairs(primefactor(n)) do
+ if v > 1 then
+ return 0
+ end
+ z = z + 1
+ end
+ if z % 2 == 0 then
+ return 1
+ end
+ return -1
+end
+
+if moebius(5) == -1 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if moebius(10) == 1 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if moebius(20) == 0 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
diff --git a/challenge-159/roger-bell-west/perl/ch-1.pl b/challenge-159/roger-bell-west/perl/ch-1.pl
new file mode 100755
index 0000000000..e99d1d11f3
--- /dev/null
+++ b/challenge-159/roger-bell-west/perl/ch-1.pl
@@ -0,0 +1,56 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 3;
+use List::Util qw(reduce);
+
+is_deeply(farey(5),[
+ [0, 1], [1, 5], [1, 4], [1, 3], [2, 5], [1, 2], [3, 5], [2, 3],
+ [3, 4], [4, 5], [1, 1]
+ ],'example 1');
+
+is_deeply(farey(7),[
+ [0, 1], [1, 7], [1, 6], [1, 5], [1, 4], [2, 7], [1, 3], [2, 5],
+ [3, 7], [1, 2], [4, 7], [3, 5], [2, 3], [5, 7], [3, 4], [4, 5],
+ [5, 6], [6, 7], [1, 1]
+ ],'example 2');
+
+is_deeply(farey(4),[
+ [0, 1], [1, 4], [1, 3], [1, 2], [2, 3], [3, 4], [1, 1]
+ ],'example 3');
+
+sub gcd {
+ my ($m,$n)=@_;
+ while ($n!=0) {
+ ($m,$n)=($n,$m % $n);
+ }
+ return $m;
+}
+
+sub lcm {
+ my ($m,$n)=@_;
+ return $m/gcd($m,$n)*$n;
+}
+
+sub lcmseries {
+ my $s=shift;
+ return reduce {lcm($a,$b)} @{$s};
+}
+
+sub farey {
+ my $n=shift;
+ my $l=lcmseries([2..$n]);
+ my %d;
+ foreach my $i (1..$n) {
+ my $m=$l/$i;
+ foreach my $j (0..$i) {
+ my $k=$m*$j;
+ unless (exists $d{$k}) {
+ $d{$k}=[$j,$i];
+ }
+ }
+ }
+ return [map {$d{$_}} sort {$a <=> $b} keys %d];
+}
diff --git a/challenge-159/roger-bell-west/perl/ch-2.pl b/challenge-159/roger-bell-west/perl/ch-2.pl
new file mode 100755
index 0000000000..4893c02740
--- /dev/null
+++ b/challenge-159/roger-bell-west/perl/ch-2.pl
@@ -0,0 +1,78 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 3;
+
+is(moebius(5),-1,'example 1');
+is(moebius(10),1,'example 2');
+is(moebius(20),0,'example 3');
+
+sub genprimes {
+ my $mx=shift;
+ my @primes;
+ {
+ my %primesh=map {$_ => 1} (2,3);
+ for (my $i=6;$i <= $mx+1; $i += 6) {
+ foreach my $j ($i-1,$i+1) {
+ if ($j <= $mx) {
+ $primesh{$j}=1;
+ }
+ }
+ }
+ my @q=(2,3,5,7);
+ my $p=shift @q;
+ my $mr=int(sqrt($mx));
+ while ($p <= $mr) {
+ if ($primesh{$p}) {
+ my $i=$p*$p;
+ while ($i <= $mx) {
+ delete $primesh{$i};
+ $i += $p;
+ }
+ }
+ if (scalar @q < 2) {
+ push @q,$q[-1]+4;
+ push @q,$q[-1]+2;
+ }
+ $p=shift @q;
+ }
+ @primes=sort {$a <=> $b} keys %primesh;
+ }
+ return \@primes;
+}
+
+sub primefactor {
+ my $n=shift;
+ my %f;
+ my $m=$n;
+ foreach my $p (@{genprimes(int(sqrt($n)))}) {
+ while ($m % $p == 0) {
+ $f{$p}++;
+ $m=int($m/$p);
+ if ($m == 1) {
+ last;
+ }
+ }
+ }
+ if ($m > 1) {
+ $f{$m}++;
+ }
+ return \%f;
+}
+
+sub moebius {
+ my $n=shift;
+ my $z=0;
+ foreach my $v (values %{primefactor($n)}) {
+ if ($v>1) {
+ return 0;
+ }
+ $z++;
+ }
+ if ($z % 2 == 0) {
+ return 1;
+ }
+ return -1;
+}
diff --git a/challenge-159/roger-bell-west/postscript/ch-1.ps b/challenge-159/roger-bell-west/postscript/ch-1.ps
new file mode 100644
index 0000000000..30c9d167ab
--- /dev/null
+++ b/challenge-159/roger-bell-west/postscript/ch-1.ps
@@ -0,0 +1,256 @@
+%!PS
+
+% begin library code
+
+/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
+
+/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
+
+/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
+
+/quicksort { % [ a c b ] -> [ a b c ]
+ 1 dict begin
+ /arr exch def
+ 0 arr length 1 sub quicksort.main
+ arr
+ 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.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 ge {
+ exit
+ } if
+ } loop
+ {
+ /j j 1 sub def
+ arr j get pivot le {
+ exit
+ } if
+ } loop
+ i j ge {
+ j
+ exit
+ } if
+ i j quicksort.swap
+ } loop
+ 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
+
+/reduce { % array proc -> value
+ 2 dict begin
+ /p exch def
+ /a exch def
+ a 0 get
+ 1 1 a length 1 sub {
+ a exch get
+ p
+ } for
+ end
+} bind def
+
+
+/apush { % [a b] c -> [a b c]
+ exch
+ [ exch aload length 2 add -1 roll ]
+} bind def
+
+/map { % array proc -> array
+ 2 dict begin
+ /p exch def
+ [ exch
+ {
+ p
+ } forall
+ ]
+} bind def
+
+/keys { % dict -> array of dict keys
+ [ exch
+ {
+ pop
+ } forall
+ ]
+} bind def
+
+% end library code
+
+/gcd {
+ {
+ dup
+ 3 1 roll
+ mod
+ dup 0 eq {
+ pop exit
+ } if
+ } loop
+} bind def
+
+/lcm {
+ dup 3 -1 roll
+ dup 4 -1 roll
+ gcd idiv mul
+} bind def
+
+/lcmseries {
+ { lcm } reduce
+} bind def
+
+/farey {
+ 7 dict begin
+ /n exch def
+ /l [ 2 1 n { } for ] lcmseries def
+ /d n dup mul dict def
+ 1 1 n {
+ /i exch def
+ /m l i idiv def
+ 0 1 i {
+ /j exch def
+ /k m j mul def
+ d k known not {
+ d k [ j i ] put
+ } if
+ } for
+ } for
+ d keys quicksort { d exch get } map
+ end
+} bind def
+
+(farey) test.start
+
+5 farey
+[ [0 1] [1 5] [1 4] [1 3] [2 5] [1 2] [3 5] [2 3] [3 4] [4 5] [1 1] ]
+deepeq test
+
+7 farey
+[ [0 1] [1 7] [1 6] [1 5] [1 4] [2 7] [1 3] [2 5] [3 7] [1 2] [4 7]
+ [3 5] [2 3] [5 7] [3 4] [4 5] [5 6] [6 7] [1 1] ]
+deepeq test
+
+4 farey
+[ [0 1] [1 4] [1 3] [1 2] [2 3] [3 4] [1 1] ]
+deepeq test
+
+test.end
diff --git a/challenge-159/roger-bell-west/postscript/ch-2.ps b/challenge-159/roger-bell-west/postscript/ch-2.ps
new file mode 100644
index 0000000000..bfc28ad691
--- /dev/null
+++ b/challenge-159/roger-bell-west/postscript/ch-2.ps
@@ -0,0 +1,217 @@
+%!PS
+
+% begin library code
+
+/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
+
+/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 { % [ a c b ] -> [ a b c ]
+ 1 dict begin
+ /arr exch def
+ 0 arr length 1 sub quicksort.main
+ arr
+ 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.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 ge {
+ exit
+ } if
+ } loop
+ {
+ /j j 1 sub def
+ arr j get pivot le {
+ exit
+ } if
+ } loop
+ i j ge {
+ j
+ exit
+ } if
+ i j quicksort.swap
+ } loop
+ 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
+
+/apush { % [a b] c -> [a b c]
+ exch
+ [ exch aload length 2 add -1 roll ]
+} bind def
+
+/values { % dict -> array of dict values
+ [ exch
+ {
+ exch pop
+ } forall
+ ]
+} bind def
+
+% end library code
+
+/genprimes {
+ /mx exch def
+ /primesh mx dict def
+ 2 1 3 {
+ primesh exch true put
+ } for
+ 6 6 mx 1 add {
+ dup 1 sub exch 1 add 2 exch {