aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xchallenge-162/roger-bell-west/javascript/ch-1.js52
-rwxr-xr-xchallenge-162/roger-bell-west/javascript/ch-2.js100
-rw-r--r--challenge-162/roger-bell-west/kotlin/ch-1.kt51
-rw-r--r--challenge-162/roger-bell-west/kotlin/ch-2.kt96
-rwxr-xr-xchallenge-162/roger-bell-west/lua/ch-1.lua53
-rwxr-xr-xchallenge-162/roger-bell-west/lua/ch-2.lua99
-rwxr-xr-xchallenge-162/roger-bell-west/perl/ch-1.pl35
-rwxr-xr-xchallenge-162/roger-bell-west/perl/ch-2.pl96
-rw-r--r--challenge-162/roger-bell-west/postscript/ch-1.ps87
-rw-r--r--challenge-162/roger-bell-west/postscript/ch-2.ps257
-rwxr-xr-xchallenge-162/roger-bell-west/python/ch-1.py48
-rwxr-xr-xchallenge-162/roger-bell-west/python/ch-2.py84
-rwxr-xr-xchallenge-162/roger-bell-west/raku/ch-1.p634
-rwxr-xr-xchallenge-162/roger-bell-west/raku/ch-2.p693
-rwxr-xr-xchallenge-162/roger-bell-west/ruby/ch-1.rb49
-rwxr-xr-xchallenge-162/roger-bell-west/ruby/ch-2.rb93
-rwxr-xr-xchallenge-162/roger-bell-west/rust/ch-1.rs55
-rwxr-xr-xchallenge-162/roger-bell-west/rust/ch-2.rs106
18 files changed, 1488 insertions, 0 deletions
diff --git a/challenge-162/roger-bell-west/javascript/ch-1.js b/challenge-162/roger-bell-west/javascript/ch-1.js
new file mode 100755
index 0000000000..352d732648
--- /dev/null
+++ b/challenge-162/roger-bell-west/javascript/ch-1.js
@@ -0,0 +1,52 @@
+#! /usr/bin/node
+
+function generate(in0) {
+ let in1 = in0.replace(/[^0-9]+/g,"")
+ if (in1.length < 12) {
+ return 99
+ }
+ in1 = in1.substring(0,12)
+ let s = 0
+ let m = 1
+ for (let i of String(in1)) {
+ s += parseInt(i) * m
+ m = 4 - m
+ }
+ return (10-(s % 10)) % 10
+}
+
+function validate(in0) {
+ let in1 = in0.replace(/[^0-9]+/g,"")
+ if (in1.length < 13) {
+ return false
+ }
+ return generate(in1) == parseInt(in1.charAt(12))
+}
+
+if (generate("978-0-306-40615-") == 7) {
+ process.stdout.write("Pass")
+} else {
+ process.stdout.write("FAIL")
+}
+process.stdout.write(" ");
+
+if (generate("978-0-306-40615-7") == 7) {
+ process.stdout.write("Pass")
+} else {
+ process.stdout.write("FAIL")
+}
+process.stdout.write(" ");
+
+if (validate("978-0-306-40615-7") == true) {
+ process.stdout.write("Pass")
+} else {
+ process.stdout.write("FAIL")
+}
+process.stdout.write(" ");
+
+if (validate("978-0-306-46015-7") == false) {
+ process.stdout.write("Pass")
+} else {
+ process.stdout.write("FAIL")
+}
+process.stdout.write("\n");
diff --git a/challenge-162/roger-bell-west/javascript/ch-2.js b/challenge-162/roger-bell-west/javascript/ch-2.js
new file mode 100755
index 0000000000..adfa0aa2dc
--- /dev/null
+++ b/challenge-162/roger-bell-west/javascript/ch-2.js
@@ -0,0 +1,100 @@
+#! /usr/bin/node
+
+function posmod(a,b) {
+ let m = a % b
+ while (m < 0) {
+ m += b
+ }
+ return m
+}
+
+function playfair(dir,kwi0,input) {
+ let kw = ""
+ let k = new Map()
+ let kwi = kwi0.toLowerCase().replace(/[^a-z]+/g,"")
+ for (let lx = 'a'.charCodeAt(0); lx <= 'z'.charCodeAt(0); lx++) {
+ kwi = kwi + String.fromCharCode(lx)
+ }
+ for (let char0 of kwi.split("")) {
+ let char1 = char0
+ if (char1 == 'j') {
+ char1 = 'i'
+ }
+ if (!k.has(char1)) {
+ k.set(char1,true)
+ kw = kw + char1
+ }
+ }
+ let grid = []
+ let gc = new Map()
+ let index = 0
+ for (let row = 0; row <= 4; row++) {
+ let r = []
+ for (let column = 0; column <= 4; column++) {
+ r.push(kw.charAt(index))
+ gc.set(kw.charAt(index),[row,column])
+ index++
+ }
+ grid.push(r)
+ }
+ let ii = input.toLowerCase().replace(/[^a-z]+/g,"").replace(/j/g,"i")
+ let out = ""
+ index = 0
+ while (index < ii.length) {
+ let ca = ii.charAt(index)
+ let cb = "x"
+ if (index + 1 < ii.length) {
+ cb = ii.charAt(index+1)
+ }
+ index += 2
+ if (ca == cb) {
+ cb = "x"
+ index--
+ }
+ let car = gc.get(ca)[0]
+ let cac = gc.get(ca)[1]
+ let cbr = gc.get(cb)[0]
+ let cbc = gc.get(cb)[1]
+ let oar = car
+ let oac = cac
+ let obr = cbr
+ let obc = cbc
+ if (car == cbr) {
+ oac = posmod(cac + dir, 5)
+ obc = posmod(cbc + dir, 5)
+ } else if (cac == cbc) {
+ oar = posmod(car + dir, 5)
+ obr = posmod(cbr + dir, 5)
+ } else {
+ oac = cbc
+ obc = cac
+ }
+ out = out + grid[oar][oac]
+ out = out + grid[obr][obc]
+ }
+ return out
+}
+
+function encrypt(kw,plaintext) {
+ return playfair(1,kw,plaintext)
+}
+
+function decrypt(kw,ciphertext) {
+ return playfair(-1,kw,ciphertext)
+}
+
+if (encrypt("playfair example","hide the gold in the tree stump") ==
+ "bmodzbxdnabekudmuixmmouvif") {
+ process.stdout.write("Pass")
+} else {
+ process.stdout.write("FAIL")
+}
+process.stdout.write(" ");
+
+if (decrypt("perl and raku","siderwrdulfipaarkcrw") ==
+ "thewexeklychallengex") {
+ process.stdout.write("Pass")
+} else {
+ process.stdout.write("FAIL")
+}
+process.stdout.write("\n");
diff --git a/challenge-162/roger-bell-west/kotlin/ch-1.kt b/challenge-162/roger-bell-west/kotlin/ch-1.kt
new file mode 100644
index 0000000000..fc35aa2bde
--- /dev/null
+++ b/challenge-162/roger-bell-west/kotlin/ch-1.kt
@@ -0,0 +1,51 @@
+fun generate(in0: String): Int {
+ val re = "[^0-9]+".toRegex()
+ var in1 = re.replace(in0,"")
+ if (in1.length < 12) {
+ return 99
+ }
+ in1 = in1.substring(0..11)
+ var s = 0
+ var m = 1
+ for (i in in1.toCharArray().toList()) {
+ s += m * i.digitToInt()
+ m = 4 - m
+ }
+ return (10-(s % 10)) % 10
+}
+
+fun validate(in0: String): Boolean {
+ val re = "[^0-9]+".toRegex()
+ var in1 = re.replace(in0,"")
+ if (in1.length != 13) {
+ return false
+ }
+ return generate(in1) == in1.get(12).digitToInt()
+}
+
+fun main() {
+ if (generate("978-0-306-40615-") == 7) {
+ print("Pass")
+ } else {
+ print("FAIL")
+ }
+ print(" ")
+ if (generate("978-0-306-40615-7") == 7) {
+ print("Pass")
+ } else {
+ print("FAIL")
+ }
+ print(" ")
+ if (validate("978-0-306-40615-7") == true) {
+ print("Pass")
+ } else {
+ print("FAIL")
+ }
+ print(" ")
+ if (validate("978-0-306-46015-7") == false) {
+ print("Pass")
+ } else {
+ print("FAIL")
+ }
+ println("")
+}
diff --git a/challenge-162/roger-bell-west/kotlin/ch-2.kt b/challenge-162/roger-bell-west/kotlin/ch-2.kt
new file mode 100644
index 0000000000..bf1fe865ac
--- /dev/null
+++ b/challenge-162/roger-bell-west/kotlin/ch-2.kt
@@ -0,0 +1,96 @@
+fun posmod(a: Int, b: Int): Int {
+ var m = a % b
+ while (m < 0) {
+ m = m + b
+ }
+ return m
+}
+
+fun playfair(dir: Int, kwi0: String, input: String): String {
+ var kw = ""
+ var k = mutableMapOf<Char, Boolean>()
+ val re = "[^a-z]+".toRegex()
+ val rej = "j".toRegex()
+ val kwi = kwi0.lowercase().replace(re,"") + ('a'..'z').joinToString("")
+ for (char0 in kwi.toCharArray().toList()) {
+ var char = char0
+ if (char == 'j') {
+ char = 'i'
+ }
+ if (!k.contains(char)) {
+ k[char] = true
+ kw = kw + char
+ }
+ }
+ var grid = ArrayList<ArrayList<Char>>()
+ var gc = mutableMapOf<Char,Pair<Int,Int>>()
+ var index = 0
+ for (row in 0..4) {
+ var r = ArrayList<Char>()
+ for (column in 0..4) {
+ r.add(kw.get(index))
+ gc[kw.get(index)] = Pair(row,column)
+ index = index + 1
+ }
+ grid.add(r)
+ }
+ val ii = input.lowercase().replace(re,"").replace(rej,"i")
+ var out = ""
+ index = 0
+ while (index < ii.length) {
+ val ca = ii.get(index)
+ var cb = 'x'
+ if (index + 1 < ii.length) {
+ cb = ii.get(index+1)
+ }
+ index = index + 2
+ if (ca == cb) {
+ cb = 'x'
+ index = index - 1
+ }
+ val (car,cac) = gc[ca]!!
+ val (cbr,cbc) = gc[cb]!!
+ var oar = car
+ var oac = cac
+ var obr = cbr
+ var obc = cbc
+ if (car == cbr) {
+ oac = posmod(cac + dir, 5)
+ obc = posmod(cbc + dir, 5)
+ } else if (cac == cbc) {
+ oar = posmod(car + dir, 5)
+ obr = posmod(cbr + dir, 5)
+ } else {
+ oac = cbc
+ obc = cac
+ }
+ out = out + grid[oar][oac]
+ out = out + grid[obr][obc]
+ }
+ return out
+}
+
+fun encrypt(kw: String,plaintext: String): String {
+ return playfair(1,kw,plaintext)
+}
+
+fun decrypt(kw: String,ciphertext: String): String {
+ return playfair(-1,kw,ciphertext)
+}
+
+fun main() {
+ if (encrypt("playfair example","hide the gold in the tree stump") ==
+ "bmodzbxdnabekudmuixmmouvif") {
+ print("Pass")
+ } else {
+ print("FAIL")
+ }
+ print(" ")
+ if (decrypt("perl and raku","siderwrdulfipaarkcrw") ==
+ "thewexeklychallengex") {
+ print("Pass")
+ } else {
+ print("FAIL")
+ }
+ println("")
+}
diff --git a/challenge-162/roger-bell-west/lua/ch-1.lua b/challenge-162/roger-bell-west/lua/ch-1.lua
new file mode 100755
index 0000000000..89538f783d
--- /dev/null
+++ b/challenge-162/roger-bell-west/lua/ch-1.lua
@@ -0,0 +1,53 @@
+#! /usr/bin/lua
+
+function generate(in0)
+ local in1=string.gsub(in0,"%D+","")
+ if string.len(in1) < 12 then
+ return 99
+ end
+ local s = 0
+ local m = 1
+ local zero = string.byte("0")
+ for i = 1, 12 do
+ s = s + m * (string.byte(string.sub(in1,i,i)) - zero)
+ m = 4 - m
+ end
+ return (10 - (s % 10)) % 10
+end
+
+function validate(in0)
+ local in1=string.gsub(in0,"%D+","")
+ if string.len(in1) ~= 13 then
+ return false
+ end
+ local zero = string.byte("0")
+ return generate(in1) == string.byte(string.sub(in1,13,13)) - zero
+end
+
+if generate("978-0-306-40615-") == 7 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if generate("978-0-306-40615-7") == 7 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if validate("978-0-306-40615-7") then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if not validate("978-0-306-46015-7") then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
diff --git a/challenge-162/roger-bell-west/lua/ch-2.lua b/challenge-162/roger-bell-west/lua/ch-2.lua
new file mode 100755
index 0000000000..13eaeb85e6
--- /dev/null
+++ b/challenge-162/roger-bell-west/lua/ch-2.lua
@@ -0,0 +1,99 @@
+#! /usr/bin/lua
+
+function encrypt(kw,plaintext)
+ return playfair(1,kw,plaintext)
+end
+
+function decrypt(kw,plaintext)
+ return playfair(-1,kw,plaintext)
+end
+
+function playfair(dir,kwi0,input)
+ local kwi=string.lower(kwi0)
+ for cc = string.byte("a"),string.byte("z") do
+ kwi = kwi .. string.char(cc)
+ end
+ local kw = ""
+ local k = {}
+ for char in string.gmatch(kwi,"(%l)") do
+ if char == "j" then
+ char = "i"
+ end
+ if k[char] == nil then
+ k[char] = true
+ kw = kw .. char
+ end
+ end
+ local grid = {}
+ local gc = {}
+ local index = 1
+ for row = 0,4 do
+ local r = {}
+ for column = 0,4 do
+ local cc=string.sub(kw,index,index)
+ table.insert(r,cc)
+ gc[cc] = {row,column}
+ index = index + 1
+ end
+ table.insert(grid,r)
+ end
+ local ii = string.gsub(string.gsub(string.lower(input),"%L+",""),"j","i")
+ local iil = string.len(ii)
+ local out = ""
+ index = 1
+ while index <= iil do
+ local ca = string.sub(ii,index,index)
+ local cb = "x"
+ if index+1 <= iil then
+ cb = string.sub(ii,index+1,index+1)
+ end
+ index = index + 2
+ if ca == cb then
+ cb = "x"
+ index = index - 1
+ end
+ local car = gc[ca][1]
+ local cac = gc[ca][2]
+ local cbr = gc[cb][1]
+ local cbc = gc[cb][2]
+ local oar = car
+ local oac = cac
+ local obr = cbr
+ local obc = cbc
+ if car == cbr then
+ oac = posmod(cac+dir,5)
+ obc = posmod(cbc+dir,5)
+ elseif cac == cbc then
+ oar = posmod(car+dir,5)
+ obr = posmod(cbr+dir,5)
+ else
+ oac = cbc
+ obc = cac
+ end
+ out = out .. grid[oar + 1][oac + 1]
+ out = out .. grid[obr + 1][obc + 1]
+ end
+ return out
+end
+
+function posmod(a,b)
+ local m = a % b
+ while m < 0 do
+ m = m + b
+ end
+ return m
+end
+
+if encrypt("playfair example","hide the gold in the tree stump") == "bmodzbxdnabekudmuixmmouvif" then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if decrypt("perl and raku","siderwrdulfipaarkcrw") == "thewexeklychallengex" then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
diff --git a/challenge-162/roger-bell-west/perl/ch-1.pl b/challenge-162/roger-bell-west/perl/ch-1.pl
new file mode 100755
index 0000000000..50abf25489
--- /dev/null
+++ b/challenge-162/roger-bell-west/perl/ch-1.pl
@@ -0,0 +1,35 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 4;
+
+is(generate("978-0-306-40615-"),7,'example 1');
+is(generate("978-0-306-40615-7"),7,'example 2');
+is(validate("978-0-306-40615-7"),1,'example 3');
+is(validate("978-0-306-46015-7"),0,'example 4');
+
+sub generate {
+ my $in = shift;
+ $in =~ s/[^0-9]+//g;
+ if (length($in) < 12) {
+ return 99;
+ }
+ my $s=0;
+ my $m=1;
+ foreach my $i (0..11) {
+ $s += substr($in,$i,1) * $m;
+ $m = 4 - $m;
+ }
+ return (10-($s % 10)) % 10;
+}
+
+sub validate {
+ my $in = shift;
+ $in =~ s/[^0-9]+//g;
+ if (length($in) != 13) {
+ return 0;
+ }
+ return (generate($in)+0 == substr($in,12,1)+0)?1:0;
+}
diff --git a/challenge-162/roger-bell-west/perl/ch-2.pl b/challenge-162/roger-bell-west/perl/ch-2.pl
new file mode 100755
index 0000000000..b2de00e1cc
--- /dev/null
+++ b/challenge-162/roger-bell-west/perl/ch-2.pl
@@ -0,0 +1,96 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+
+is(encrypt("playfair example",
+ "hide the gold in the tree stump"),
+ "bmodzbxdnabekudmuixmmouvif",'example 1');
+
+is(decrypt("perl and raku",
+ "siderwrdulfipaarkcrw"),
+ "thewexeklychallengex",'example 2');
+
+sub encrypt {
+ my ($kw,$plaintext)=@_;
+ return playfair(1,$kw,$plaintext);
+}
+
+sub decrypt {
+ my ($kw,$ciphertext)=@_;
+ return playfair(-1,$kw,$ciphertext);
+}
+
+sub playfair {
+ my ($dir,$kwi,$input)=@_;
+ my $kw='';
+ {
+ my %k;
+ foreach my $char (split '',lc($kwi).join('','a'..'z')) {
+ if ($char eq 'j') {
+ $char='i';
+ }
+ if ($char =~ /[a-z]/) {
+ unless (exists $k{$char}) {
+ $k{$char}=1;
+ $kw.=$char;
+ }
+ }
+ }
+ }
+ my @grid;
+ my %gc;
+ {
+ my $index=0;
+ foreach my $row (0..4) {
+ my @r;
+ foreach my $column (0..4) {
+ push @r,substr($kw,$index,1);
+ $gc{substr($kw,$index,1)}=[$row,$column];
+ $index++;
+ }
+ push @grid, \@r;
+ }
+ }
+ my $ii=lc($input);
+ $ii =~ s/[^a-z]//g;
+ $ii =~ s/j/i/g;
+ my @ichars=split '',$ii;
+ my $out = '';
+ my $index=0;
+ while ($index < scalar @ichars) {
+ my $ca=$ichars[$index];
+ my $cb=$ichars[$index+1] || 'x';
+ $index+=2;
+ if ($ca eq $cb) {
+ $cb='x';
+ $index--;
+ }
+ my ($car,$cac)=@{$gc{$ca}};
+ my ($cbr,$cbc)=@{$gc{$cb}};
+ my ($oar,$oac,$obr,$obc)=($car,$cac,$cbr,$cbc);
+ if ($car == $cbr) {
+ $oac=posmod($cac+$dir,5);
+ $obc=posmod($cbc+$dir,5);
+ } elsif ($cac == $cbc) {
+ $oar=posmod($car+$dir,5);
+ $obr=posmod($cbr+$dir,5);
+ } else {
+ $oac=$cbc;
+ $obc=$cac;
+ }
+ $out .= $grid[$oar][$oac] . $grid[$obr][$obc];
+ }
+ return $out;
+}
+
+sub posmod {
+ my ($a,$b)=@_;
+ my $m=$a % $b;
+ while ($m < 0) {
+ $m += $b;
+ }
+ return $m;
+}
diff --git a/challenge-162/roger-bell-west/postscript/ch-1.ps b/challenge-162/roger-bell-west/postscript/ch-1.ps
new file mode 100644
index 0000000000..f760d6e8a0
--- /dev/null
+++ b/challenge-162/roger-bell-west/postscript/ch-1.ps
@@ -0,0 +1,87 @@
+%!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
+
+% end library code
+
+/generate {
+ 3 dict begin
+ /l 0 def
+ /s 0 def
+ /m 1 def
+ {
+ dup dup 48 ge exch 57 le and {
+ /l l 1 add def
+ 48 sub m mul s add /s exch def
+ /m 4 m sub def
+ l 12 ge {
+ exit
+ } if
+ } if
+ } forall
+ l 12 lt {
+ 99
+ } {
+ 10 s 10 mod sub 10 mod
+ } ifelse
+ (..) cvs
+ end
+} bind def
+
+/validate {
+ 3 dict begin
+ /partial 12 string def
+ /check 0 def
+ /l 0 def
+ {
+ dup dup 48 ge exch 57 le and {
+ l 11 le {
+ partial exch l exch put
+ /l l 1 add def
+ } {
+ 48 sub /check exch def
+ exit
+ } ifelse
+ } if
+ } forall
+ partial generate cvi check eq
+ end
+} bind def
+
+(isbn) test.start
+(978-0-306-40615-) generate (7) eq test
+(978-0-306-40615-7) generate (7) eq test
+(978-0-306-40615-7) validate test
+(978-0-306-46015-7) validate not test
+test.end
diff --git a/challenge-162/roger-bell-west/postscript/ch-2.ps b/challenge-162/roger-bell-west/postscript/ch-2.ps
new file mode 100644
index 0000000000..0531f7c205
--- /dev/null
+++ b/challenge-162/roger-bell-west/postscript/ch-2.ps
@@ -0,0 +1,257 @@
+%!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
+
+/s2a {
+ [ exch { } forall ]
+} bind def
+
+/a2s {
+ 2 dict begin
+ /i exch def
+ i length dup string /o exch def
+ 1 sub 0 exch 1 exch {
+ dup i 3 -1 roll get o 3 1 roll put
+ } for
+ o
+ end
+} bind def
+
+/apush.right { % [a b] c -> [a b c]
+ exch
+ [ exch aload length 2 add -1 roll ]
+} bind def
+
+% end library code
+
+/encrypt {
+ 1 3 1 roll playfair
+} bind def
+
+/decrypt {
+ -1 3 1 roll playfair
+} bind def
+
+/posmod {
+ 1 dict begin
+ dup /b exch def
+ mod
+ {
+ dup 0 lt {
+ b add
+ } {
+ exit
+ } ifelse
+ } loop
+ end
+} bind def
+
+/playfair {
+ 3 dict begin
+ /input exch def
+ /kwi exch def
+ /dir exch def
+ /ii input length string def
+ /l 0 def
+ input {
+ dup dup 65 ge exch 90 le and {
+ 32 add
+ } if
+ dup 106 eq {
+ pop 105
+ } if
+ dup dup 97 ge exch 122 le and {
+ ii exch l exch put
+ /l l 1 add def
+ } {
+ pop
+ } ifelse
+ } forall
+ ii 0 l getinterval s2a /ichars exch def
+ /kw 26 string def
+ /k 26 dict def
+ /l 0 def
+ kwi {
+ dup dup 65 ge exch 90 le and {
+ 32 add
+ } if
+ dup dup 97 ge exch 122 le and {
+ dup k exch known not {
+ dup kw exch l exch put
+ /l l 1 add def
+ k exch true put
+ } {
+ pop
+ } ifelse
+ } {
+ pop
+ } ifelse
+ } forall
+ (j) { k exch true put } forall
+ 97 1 122 {
+ dup k exch known not {
+ kw exch l exch put
+ /l l 1 add def
+ l 26 ge {
+ exit
+ } if
+ } {
+ pop
+ } ifelse
+ } for
+ /grid 5 array def
+ /gc 26 dict def
+ /ix 0 def
+ 0 1 4 {
+ /row exch def
+ /r 5 array def
+ 0 1 4 {
+ /column exch def
+ r column kw ix get put
+ gc kw ix get [ row column ] put
+ /ix ix 1 add def
+ } for
+ grid row r put
+ } for
+ /ix 0 def
+ [
+ {
+ ix ichars length ge {
+ exit
+ } if
+ /ca ichars ix get def
+ /cb
+ ix 1 add ichars length ge {
+ (x) { } forall
+ } {
+ ichars ix 1 add get
+ } ifelse
+ def
+ /ix ix 2 add def
+ ca cb eq {
+ /cb (x) { } forall def
+ /ix ix 1 sub def
+ } if
+ /car gc ca get 0 get def
+ /cac gc ca get 1 get def
+ /cbr gc cb get 0 get def
+ /cbc gc cb get 1 get def
+ /oar car def
+ /oac cac def
+ /obr cbr def
+ /obc cbc def
+ 1 {
+ car cbr eq {
+ /oac cac dir add 5 posmod def
+ /obc cbc dir add 5 posmod def
+ exit
+ } if
+ cac cbc eq {
+ /oar car dir add 5 posmod def
+ /obr cbr dir add 5 posmod def
+ exit
+ } if
+ /oac cbc def
+ /obc cac def
+ } repeat
+ grid oar get oac get
+ grid obr get obc get
+ } loop
+ ]
+ a2s
+ end
+} bind def
+
+(playfair) test.start
+(playfair example) (hide the gold in the tree stump) encrypt (bmodzbxdnabekudmuixmmouvif) deepeq test
+(perl and raku) (siderwrdulfipaarkcrw) decrypt (thewexeklychallengex) deepeq test
+test.end
diff --git a/challenge-162/roger-bell-west/python/ch-1.py b/challenge-162/roger-bell-west/python/ch-1.py
new file mode 100755
index 0000000000..4d0a8581b4
--- /dev/null
+++ b/challenge-162/roger-bell-west/python/ch-1.py
@@ -0,0 +1,48 @@
+#! /usr/bin/python3
+
+import unittest
+
+import re
+
+def generate(in0):
+ rnd = re.compile(r"[^0-9]+")
+ in1 = rnd.sub("",in0)
+ if len(in1) < 12:
+ return 99
+ s = 0
+ m = 1
+ for i in in1[0:12]:
+ s += int(i) * m
+ m = 4 - m
+ return (10-(s % 10)) % 10
+
+def validate(in0):
+ rnd = re.compile(r"[^0-9]+")
+ in1 = rnd.sub("",in0)
+ if len(in1) != 13:
+ return False
+ return generate(in1) == int(in1[-1])
+
+class TestIsbn(unittest.TestCase):
+
+ def test_ex1(self):
+ self.assertEqual(generate("978-0-306-40615-"),
+ 7,
+ 'example 1')
+
+ def test_ex2(self):
+ self.assertEqual(generate("978-0-306-40615-7"),
+ 7,
+ 'example 2')
+
+ def test_ex3(self):
+ self.assertEqual(validate("978-0-306-40615-7"),
+ True,
+ 'example 3')
+
+ def test_ex4(self):
+ self.assertEqual(validate("978-0-306-46015-7"),
+ False,
+ 'example 4')
+
+unittest.main()
diff --git a/challenge-162/roger-bell-west/python/ch-2.py b/challenge-162/roger-bell-west/python/ch-2.py
new file mode 100755
index 0000000000..fdd8623583
--- /dev/null
+++ b/challenge-162/roger-bell-west/python/ch-2.py
@@ -0,0 +1,84 @@
+#! /usr/bin/python3
+
+import unittest
+
+import re
+import string
+
+def encrypt(kw,plaintext):
+ return playfair(1,kw,plaintext)
+
+def decrypt(kw,ciphertext):
+ return playfair(-1,kw,ciphertext)
+
+def posmod(a,b):
+ m = a % b
+ while m < 0:
+ m += b
+ return m
+
+def stripnonalpha(src):
+ bad = re.compile(r"[^a-z]+")
+ out = bad.sub("",src.lower());
+ j = re.compile(r"j")
+ return j.sub("i",out);
+
+def playfair(dir, kwi0, inp):
+ kw = ""
+ k = set()
+ for c in stripnonalpha(kwi0 + string.ascii_lowercase):
+ if not c in k:
+ kw += c
+ k.add(c)
+ grid = []
+ gc = dict()
+ index = 0
+ for row in range(5):
+ r = []
+ for column in range(5):
+ r.append(kw[index])
+ gc[kw[index]] = [row,column]
+ index += 1
+ grid.append(r)
+ ii = stripnonalpha(inp)
+ index = 0
+ out = ""
+ while index < len(ii):
+ ca = ii[index]
+ cb = "x"
+ if index + 1 < len(ii):
+ cb = ii[index+1]
+ index += 2
+ if ca == cb:
+ cb = "x"
+ index -= 1
+ car,cac = gc[ca]
+ cbr,cbc = gc[cb]
+ oar,oac,obr,obc = car,cac,cbr,cbc
+ if car == cbr:
+ oac = posmod(cac + dir, 5)
+ obc = posmod(cbc + dir, 5)
+ elif cac == cbc:
+ oar = posmod(car + dir, 5)
+ obr = posmod(cbr + dir, 5)
+ else:
+ oac = cbc
+ obc = cac
+ out += grid[oar][oac] + grid[obr][obc]
+ return out
+
+class TestPlayfair(unittest.TestCase):
+
+ def test_ex1(self):
+ self.assertEqual(encrypt("playfair example",
+ "hide the gold in the tree stump"),
+ "bmodzbxdnabekudmuixmmouvif",
+ 'example 1')
+
+ def test_ex2(self):
+ self.assertEqual(decrypt("perl and raku",
+