aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2023-09-18 09:13:32 +0100
committerGitHub <noreply@github.com>2023-09-18 09:13:32 +0100
commit0d0598002c58aafbd3854e227f9fce5a511a35cd (patch)
tree4dfb5d6103230edc26fb0fc8e6bae2c03b93698b
parent8de70a3000498e9b1ec8796913973c317b62391d (diff)
parent0bd7ff4bf2020a6e93cd6be4822761d9ced0f372 (diff)
downloadperlweeklychallenge-club-0d0598002c58aafbd3854e227f9fce5a511a35cd.tar.gz
perlweeklychallenge-club-0d0598002c58aafbd3854e227f9fce5a511a35cd.tar.bz2
perlweeklychallenge-club-0d0598002c58aafbd3854e227f9fce5a511a35cd.zip
Merge pull request #8722 from Firedrake/rogerbw-challenge-234
Rogerbw challenge 234
-rwxr-xr-xchallenge-234/roger-bell-west/javascript/ch-1.js91
-rwxr-xr-xchallenge-234/roger-bell-west/javascript/ch-2.js69
-rw-r--r--challenge-234/roger-bell-west/kotlin/ch-1.kt62
-rw-r--r--challenge-234/roger-bell-west/kotlin/ch-2.kt65
-rwxr-xr-xchallenge-234/roger-bell-west/lua/ch-1.lua112
-rwxr-xr-xchallenge-234/roger-bell-west/lua/ch-2.lua78
-rwxr-xr-xchallenge-234/roger-bell-west/perl/ch-1.pl44
-rwxr-xr-xchallenge-234/roger-bell-west/perl/ch-2.pl28
-rw-r--r--challenge-234/roger-bell-west/postscript/ch-1.ps204
-rw-r--r--challenge-234/roger-bell-west/postscript/ch-2.ps138
-rwxr-xr-xchallenge-234/roger-bell-west/python/ch-1.py41
-rwxr-xr-xchallenge-234/roger-bell-west/python/ch-2.py31
-rwxr-xr-xchallenge-234/roger-bell-west/raku/ch-1.p634
-rwxr-xr-xchallenge-234/roger-bell-west/raku/ch-2.p622
-rwxr-xr-xchallenge-234/roger-bell-west/ruby/ch-1.rb51
-rwxr-xr-xchallenge-234/roger-bell-west/ruby/ch-2.rb35
-rwxr-xr-xchallenge-234/roger-bell-west/rust/ch-1.rs39
-rwxr-xr-xchallenge-234/roger-bell-west/rust/ch-2.rs30
-rw-r--r--challenge-234/roger-bell-west/tests.yaml51
19 files changed, 1225 insertions, 0 deletions
diff --git a/challenge-234/roger-bell-west/javascript/ch-1.js b/challenge-234/roger-bell-west/javascript/ch-1.js
new file mode 100755
index 0000000000..de9c406186
--- /dev/null
+++ b/challenge-234/roger-bell-west/javascript/ch-1.js
@@ -0,0 +1,91 @@
+#! /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 commoncharacters(a) {
+ let ac = [];
+ for (let w of a) {
+ let h = new Map();
+ for (let c of w.split("")) {
+ if (h.has(c)) {
+ h.set(c, h.get(c) + 1);
+ } else {
+ h.set(c, 1);
+ }
+ }
+ ac.push(h);
+ }
+ let vc = new Map();
+ for (let i = 0; i < ac.length; i++) {
+ if (i == 0) {
+ for (let c of ac[i].keys()) {
+ vc.set(c, ac[i].get(c));
+ }
+ } else {
+ for (let c of vc.keys()) {
+ if (ac[i].has(c)) {
+ vc.set(c, Math.min(vc.get(c), ac[i].get(c)));
+ } else {
+ vc.delete(c);
+ }
+ }
+ }
+ }
+ let out = [];
+ for (let c of a[0].split("")) {
+ if (vc.has(c)) {
+ out.push(c);
+ vc.set(c, vc.get(c) - 1);
+ if (vc.get(c) == 0) {
+ vc.delete(c);
+ }
+ }
+ }
+ return out;
+}
+
+if (deepEqual(commoncharacters(['java', 'javascript', 'julia']), ['j', 'a'])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(commoncharacters(['bella', 'label', 'roller']), ['e', 'l', 'l'])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (deepEqual(commoncharacters(['cool', 'lock', 'cook']), ['c', 'o'])) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-234/roger-bell-west/javascript/ch-2.js b/challenge-234/roger-bell-west/javascript/ch-2.js
new file mode 100755
index 0000000000..a463ef13ac
--- /dev/null
+++ b/challenge-234/roger-bell-west/javascript/ch-2.js
@@ -0,0 +1,69 @@
+#! /usr/bin/node
+
+"use strict"
+
+function combinations(arr, k) {
+ let c = [];
+ for (let i = 0; i < k; i++) {
+ c.push(i);
+ }
+ c.push(arr.length);
+ c.push(0);
+ let out = [];
+ while (true) {
+ let inner = [];
+ for (let i = k-1; i >= 0; i--) {
+ inner.push(arr[c[i]]);
+ }
+ out.push(inner);
+ let j = 0;
+ while (c[j] + 1 == c[j + 1]) {
+ c[j] = j;
+ j += 1;
+ }
+ if (j >= k) {
+ break;
+ }
+ c[j] += 1;
+ }
+ return out;
+}
+
+function unequaltriplets(utl) {
+ let utc = new Map();
+ for (let n of utl) {
+ if (utc.has(n)) {
+ utc.set(n, utc.get(n) + 1);
+ } else {
+ utc.set(n, 1);
+ }
+ }
+ const kl = Array.from(utc.keys());
+ if (kl.length < 3) {
+ return 0;
+ }
+ let out = 0;
+ for (let c of combinations(kl, 3)) {
+ out += utc.get(c[0]) * utc.get(c[1]) * utc.get(c[2]);
+ }
+ return out;
+}
+
+if (unequaltriplets([4, 4, 2, 4, 3]) == 3) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (unequaltriplets([1, 1, 1, 1, 1]) == 0) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (unequaltriplets([4, 7, 1, 10, 7, 4, 1, 1]) == 28) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-234/roger-bell-west/kotlin/ch-1.kt b/challenge-234/roger-bell-west/kotlin/ch-1.kt
new file mode 100644
index 0000000000..f31a5d0c61
--- /dev/null
+++ b/challenge-234/roger-bell-west/kotlin/ch-1.kt
@@ -0,0 +1,62 @@
+import kotlin.math.min
+
+fun commoncharacters(a: List<String>): List<Char> {
+ var ac = ArrayList<Map<Char, Int>>()
+ for (w in a) {
+ var h = mutableMapOf<Char, Int>().withDefault({0})
+ for (c in w.toCharArray()) {
+ h.set(c, h.getValue(c) + 1)
+ }
+ ac.add(h)
+ }
+ var vc = mutableMapOf<Char, Int>()
+ for (i in 0 .. ac.size - 1) {
+ if (i == 0) {
+ for (c in ac[i].keys) {
+ vc.set(c, ac[i].get(c)!!)
+ }
+ } else {
+ for (c in vc.keys.toList()) {
+ if (ac[i].contains(c)) {
+ vc.set(c, min(vc.get(c)!!, ac[i].get(c)!!))
+ } else {
+ vc.remove(c)
+ }
+ }
+ }
+ }
+ var out = ArrayList<Char>()
+ for (c in a[0].toCharArray()) {
+ if (vc.contains(c)) {
+ out.add(c)
+ vc.set(c, vc.get(c)!! - 1)
+ if (vc.get(c)!! == 0) {
+ vc.remove(c)
+ }
+ }
+ }
+ return out.toList()
+}
+
+fun main() {
+
+ if (commoncharacters(listOf("java", "javascript", "julia")) == listOf('j', 'a')) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (commoncharacters(listOf("bella", "label", "roller")) == listOf('e', 'l', 'l')) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (commoncharacters(listOf("cool", "lock", "cook")) == listOf('c', 'o')) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-234/roger-bell-west/kotlin/ch-2.kt b/challenge-234/roger-bell-west/kotlin/ch-2.kt
new file mode 100644
index 0000000000..28a9f3a683
--- /dev/null
+++ b/challenge-234/roger-bell-west/kotlin/ch-2.kt
@@ -0,0 +1,65 @@
+fun combinations(arr: List<Int>, k: Int): List<List<Int>> {
+ var c = ArrayList<Int>()
+ for (i in 0 .. k-1) {
+ c.add(i)
+ }
+ c.add(arr.size)
+ c.add(0)
+ var out = ArrayList<List<Int>>()
+ while (true) {
+ var inner = ArrayList<Int>()
+ for (i in k-1 downTo 0) {
+ inner.add(arr[c[i]])
+ }
+ out.add(inner.toList())
+ var j = 0
+ while (c[j] + 1 == c[j + 1]) {
+ c[j] = j
+ j += 1
+ }
+ if (j >= k) {
+ break
+ }
+ c[j] += 1
+ }
+ return out.toList();
+}
+
+fun unequaltriplets(utl: List<Int>): Int {
+ var utc = mutableMapOf<Int, Int>().withDefault({0})
+ for (n in utl) {
+ utc.set(n, utc.getValue(n) + 1);
+ }
+ val kl = utc.keys.toList()
+ if (kl.size < 3) {
+ return 0
+ }
+ var out = 0
+ for (c in combinations(kl, 3)) {
+ out += utc.getValue(c[0]) * utc.getValue(c[1]) * utc.getValue(c[2]);
+ }
+ return out
+}
+
+fun main() {
+
+ if (unequaltriplets(listOf(4, 4, 2, 4, 3)) == 3) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (unequaltriplets(listOf(1, 1, 1, 1, 1)) == 0) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (unequaltriplets(listOf(4, 7, 1, 10, 7, 4, 1, 1)) == 28) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-234/roger-bell-west/lua/ch-1.lua b/challenge-234/roger-bell-west/lua/ch-1.lua
new file mode 100755
index 0000000000..09679319d9
--- /dev/null
+++ b/challenge-234/roger-bell-west/lua/ch-1.lua
@@ -0,0 +1,112 @@
+#! /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 split(t)
+ local cl = {}
+ string.gsub(t,
+ "(.)",
+ function(c)
+ table.insert(cl, c)
+ end
+ )
+ return cl
+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 commoncharacters(a)
+ local ac = {}
+ for _i, w in ipairs(a) do
+ local h = {}
+ for _j, c in ipairs(split(w)) do
+ if h[c] == nil then
+ h[c] = 1
+ else
+ h[c] = h[c] + 1
+ end
+ end
+ table.insert(ac, h)
+ end
+ local vc = deepcopy(ac[1])
+ for i, aa in ipairs(ac) do
+ if i > 1 then
+ for c, ct in pairs(vc) do
+ if aa[c] == nil then
+ vc[c] = nil
+ elseif aa[c] < vc[c] then
+ vc[c] = aa[c]
+ end
+ end
+ end
+ end
+ local out = {}
+ for _, c in ipairs(split(a[1])) do
+ if vc[c] ~= nil then
+ table.insert(out, c)
+ vc[c] = vc[c] - 1
+ if vc[c] == 0 then
+ vc[c] = nil
+ end
+ end
+ end
+ return out
+end
+
+if recursive_compare(commoncharacters({"java", "javascript", "julia"}), {"j", "a"}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(commoncharacters({"bella", "label", "roller"}), {"e", "l", "l"}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if recursive_compare(commoncharacters({"cool", "lock", "cook"}), {"c", "o"}) then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-234/roger-bell-west/lua/ch-2.lua b/challenge-234/roger-bell-west/lua/ch-2.lua
new file mode 100755
index 0000000000..6a268448b4
--- /dev/null
+++ b/challenge-234/roger-bell-west/lua/ch-2.lua
@@ -0,0 +1,78 @@
+#! /usr/bin/lua
+
+function keys(t)
+ local a = {}
+ for k, v in pairs(t) do
+ table.insert(a, k)
+ end
+ return a
+end
+
+function combinations(arr, k)
+ local c = {}
+ for i = 1, k do
+ table.insert(c, i)
+ end
+ table.insert(c, #arr + 1)
+ table.insert(c, 0)
+ local out = {}
+ while true do
+ local inner = {}
+ for i = k, 1, -1 do
+ table.insert(inner, arr[c[i]])
+ end
+ table.insert(out, inner)
+ local j = 1
+ while c[j] + 1 == c[j + 1] do
+ c[j] = j
+ j = j + 1
+ end
+ if j > k then
+ break
+ end
+ c[j] = c[j] + 1
+ end
+ return ipairs(out)
+end
+
+function unequaltriplets(utl)
+ local utc = {}
+ for _i, n in ipairs(utl) do
+ if utc[n] == nil then
+ utc[n] = 1
+ else
+ utc[n] = utc[n] + 1
+ end
+ end
+ local kl = keys(utc)
+ if #kl < 3 then
+ return 0
+ end
+ local out = 0
+ for _, c in combinations(kl, 3) do
+ out = out + utc[c[1]] * utc[c[2]] * utc[c[3]]
+ end
+ return out
+end
+
+if unequaltriplets({4, 4, 2, 4, 3}) == 3 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if unequaltriplets({1, 1, 1, 1, 1}) == 0 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if unequaltriplets({4, 7, 1, 10, 7, 4, 1, 1}) == 28 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-234/roger-bell-west/perl/ch-1.pl b/challenge-234/roger-bell-west/perl/ch-1.pl
new file mode 100755
index 0000000000..0e8095b393
--- /dev/null
+++ b/challenge-234/roger-bell-west/perl/ch-1.pl
@@ -0,0 +1,44 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use List::Util qw(min);
+use Test::More tests => 3;
+
+is_deeply(commoncharacters(['java', 'javascript', 'julia']), ['j', 'a'], 'example 1');
+is_deeply(commoncharacters(['bella', 'label', 'roller']), ['e', 'l', 'l'], 'example 2');
+is_deeply(commoncharacters(['cool', 'lock', 'cook']), ['c', 'o'], 'example 3');
+
+sub commoncharacters ($a) {
+ my @ac;
+ foreach my $w (@{$a}) {
+ my %h;
+ foreach my $c (split '', $w) {
+ $h{$c}++;
+ }
+ push @ac, \%h;
+ }
+ my %vc = %{$ac[0]};
+ foreach my $aa (@ac) {
+ foreach my $c (keys %vc) {
+ if (exists $aa->{$c}) {
+ $vc{$c} = min($vc{$c}, $aa->{$c});
+ } else {
+ delete $vc{$c};
+ }
+ }
+ }
+ my @out;
+ foreach my $c (split '', $a->[0]) {
+ if (exists $vc{$c}) {
+ push @out, $c;
+ $vc{$c}--;
+ if ($vc{$c} == 0) {
+ delete $vc{$c};
+ }
+ }
+ }
+ return \@out;
+}
diff --git a/challenge-234/roger-bell-west/perl/ch-2.pl b/challenge-234/roger-bell-west/perl/ch-2.pl
new file mode 100755
index 0000000000..a7b9a35386
--- /dev/null
+++ b/challenge-234/roger-bell-west/perl/ch-2.pl
@@ -0,0 +1,28 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 3;
+use Algorithm::Combinatorics qw(combinations);
+
+is(unequaltriplets([4, 4, 2, 4, 3]), 3, 'example 1');
+is(unequaltriplets([1, 1, 1, 1, 1]), 0, 'example 2');
+is(unequaltriplets([4, 7, 1, 10, 7, 4, 1, 1]), 28, 'example 3');
+
+sub unequaltriplets($utl) {
+ my %utc;
+ foreach my $n (@{$utl}) {
+ $utc{$n}++;
+ }
+ my @kl = keys %utc;
+ if (scalar @kl < 3) {
+ return 0;
+ }
+ my $out = 0;
+ foreach my $c (combinations(\@kl, 3)) {
+ $out += $utc{$c->[0]} * $utc{$c->[1]} * $utc{$c->[2]};
+ }
+ return $out;
+}
diff --git a/challenge-234/roger-bell-west/postscript/ch-1.ps b/challenge-234/roger-bell-west/postscript/ch-1.ps
new file mode 100644
index 0000000000..8f084f182b
--- /dev/null
+++ b/challenge-234/roger-bell-west/postscript/ch-1.ps
@@ -0,0 +1,204 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/s2a {
+ [ exch { } forall ]
+} bind def
+
+/test.start {
+ print (:) print
+ /test.pass 0 def
+ /test.count 0 def
+} bind def
+
+/map { % array proc -> array
+ 2 dict begin
+ /p exch def
+ [ exch
+ {
+ p
+ } forall
+ ]
+ end
+} bind def
+
+/dget {
+ 3 1 roll
+ 2 copy
+ known {
+ get exch pop
+ } {
+ pop pop
+ } 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
+
+/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
+
+/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
+
+/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
+
+
+% end included library code
+
+/commoncharacters {
+ 0 dict begin
+ /a exch def
+ [
+ a {
+ /h 0 dict def
+ s2a {
+ /c exch def
+ h c 2 copy 0 dget 1 add put
+ } forall
+ h
+ } forall
+ ] /ac exch bind def
+ /vc ac 0 get deepcopy def
+ ac {
+ /aa exch def
+ vc keys {
+ /c exch def
+ aa c known {
+ vc c 2 copy get aa c get min put
+ } {
+ vc c undef
+ } ifelse
+ } forall
+ } forall
+ [
+ a 0 get s2a {
+ /c exch def
+ vc c known {
+ c
+ vc c 2 copy get 1 sub put
+ vc c get 0 eq {
+ vc c undef
+ } if
+ } if
+ } forall
+ ] { 1 string dup 3 2 roll 0 exch put } map
+ end
+} bind def
+
+(commoncharacters) test.start
+[(java) (javascript) (julia)] commoncharacters [(j) (a)] deepeq test
+[(bella) (label) (roller)] commoncharacters [(e) (l) (l)] deepeq test
+[(cool) (lock) (cook)] commoncharacters [(c) (o)] deepeq test
+test.end
diff --git a/challenge-234/roger-bell-west/postscript/ch-2.ps b/challenge-234/roger-bell-west/postscript/ch-2.ps
new file mode 100644
index 0000000000..4d4c35815b
--- /dev/null
+++ b/challenge-234/roger-bell-west/postscript/ch-2.ps
@@ -0,0 +1,138 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/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
+
+/combinations {
+ 4 dict begin
+ /k exch def
+ /arr exch def
+ /c [
+ 0 1 k 1 sub { } for
+ arr length
+ 0
+ ] def
+ [
+ {
+ [
+ k 1 sub -1 0 {
+ c exch get arr exch get
+ } for
+ ]
+ /j 0 def
+ {
+ c j get 1 add c j 1 add get ne {
+ exit
+ } if
+ c j j put
+ /j j 1 add def
+ } loop
+ j k ge {
+ exit
+ } if
+ c j c j get 1 add put
+ } loop
+ ]
+ end
+} bind def
+
+/keys { % dict -> array of dict keys
+ [ exch
+ {
+ pop
+ } forall
+ ]
+} 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
+
+/dget {
+ 3 1 roll
+ 2 copy
+ known {
+ get exch pop
+ } {
+ pop pop
+ } ifelse
+} 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
+
+/map { % array proc -> array
+ 2 dict begin
+ /p exch def
+ [ exch
+ {
+ p
+ } forall
+ ]
+ end
+} bind def
+
+
+% end included library code
+
+/unequaltriplets {
+ 0 dict begin
+ /utc 0 dict def
+ {
+ /n exch def
+ utc n 2 copy 0 dget 1 add put
+ } forall
+ /kl utc keys def
+ kl length 3 lt {
+ 0
+ } {
+ 0
+ kl 3 combinations {
+ /c exch def
+ [ 0 1 2 { } for ] { c exch get utc exch get } map
+ { mul } reduce add
+ } forall
+ } ifelse
+ end
+} bind def
+
+(unequaltriplets) test.start
+[4 4 2 4 3] unequaltriplets 3 eq test
+[1 1 1 1 1] unequaltriplets 0 eq test
+[4 7 1 10 7 4 1 1] unequaltriplets 28 eq test
+test.end
diff --git a/challenge-234/roger-bell-west/python/ch-1.py b/challenge-234/roger-bell-west/python/ch-1.py
new file mode 100755
index 0000000000..2c00ffcd6c
--- /dev/null
+++ b/challenge-234/roger-bell-west/python/ch-1.py
@@ -0,0 +1,41 @@
+#! /usr/bin/python3
+
+from collections import defaultdict
+
+def commoncharacters(a):
+ ac = []
+ for w in a:
+ h = defaultdict(lambda: 0)
+ for c in w:
+ h[c] += 1
+ ac.append(h)
+ vc = ac[0]
+ for aa in ac[1:]:
+ for c in list(vc.keys()):
+ if c in aa:
+ vc[c] = min(vc[c], aa[c])
+ else:
+ del vc[c]
+ out = []
+ for c in a[0]:
+ if c in vc:
+ out.append(c)
+ vc[c] -= 1
+ if vc[c] == 0:
+ del vc[c]
+ return out
+
+import unittest
+
+class TestCommoncharacters(unittest.TestCase):
+
+ def test_ex1(self):
+ self.assertEqual(commoncharacters(["java", "javascript", "julia"]), ["j", "a"], 'example 1')
+
+ def test_ex2(self):
+ self.assertEqual(commoncharacters(["bella", "label", "roller"]), ["e", "l", "l"], 'example 2')
+
+ def test_ex3(self):
+ self.assertEqual(commoncharacters(["cool", "lock", "cook"]), ["c", "o"], 'example 3')
+
+unittest.main()
diff --git a/challenge-234/roger-bell-west/python/ch-2.py b/challenge-234/roger-bell-west/python/ch-2.py
new file mode 100755
index 0000000000..dc14ee61c3
--- /dev/null
+++ b/challenge-234/roger-bell-west/python/ch-2.py
@@ -0,0 +1,31 @@
+#! /usr/bin/python3
+
+from collections import defaultdict
+from itertools import combinations
+
+def unequaltriplets(a):
+ utc = defaultdict(lambda: 0)
+ for n in a:
+ utc[n] += 1
+ kl = list(utc.keys())
+ if len(kl) < 3:
+ return 0
+ out = 0
+ for c in combinations(kl, 3):
+ out += utc[c[0]] * utc[c[1]] * utc[c[2]]
+ return out
+
+import unittest
+
+class TestUnequaltriplets(unittest.TestCase):
+
+ def test_ex1(self):
+ self.assertEqual(unequaltriplets([4, 4, 2, 4, 3]), 3, 'example 1')
+
+ def test_ex2(self):
+ self.assertEqual(unequaltriplets([1, 1, 1, 1, 1]), 0, 'example 2')
+
+ def test_ex3(self):
+ self.assertEqual(unequaltriplets([4, 7, 1, 10, 7, 4, 1, 1]), 28, 'example 3')
+
+unittest.main()
diff --git a/challenge-234/roger-bell-west/raku/ch-1.p6 b/challenge-234/roger-bell-west/raku/ch-1.p6
new file mode 100755
index 0000000000..cacfe75582
--- /dev/null
+++ b/challenge-234/roger-bell-west/raku/ch-1.p6
@@ -0,0 +1,34 @@
+#! /usr/bin/raku
+
+use Test;
+
+plan 3;
+
+is-deeply(commoncharacters(['java', 'javascript', 'julia']), ['j', 'a'], 'example 1');
+is-deeply(commoncharacters(['bella', 'label', 'roller']), ['e', 'l', 'l'], 'example 2');
+is-deeply(commoncharacters(['cool', 'lock', 'cook']), ['c', 'o'], 'example 3');
+
+sub commoncharacters (@a) {
+ my @ac;
+ for @a -> $w {
+ @ac.push($w.comb.Bag);
+ }
+ my %vc = BagHash(@ac[0]);
+ for @ac.skip(1) -> $aa {
+ for keys %vc -> $c {
+ if ($aa{$c}:exists) {
+ %vc{$c} = min(%vc{$c}, $aa{$c});
+ } else {
+ %vc{$c}:delete;
+ }
+ }<