From 12fa389d6e1dc5ab45926f20d9bc3eff560dbd52 Mon Sep 17 00:00:00 2001 From: Roger Bell_West Date: Thu, 27 Apr 2023 13:32:38 +0100 Subject: RogerBW solutions for challenge no. 214 --- challenge-214/roger-bell-west/javascript/ch-1.js | 88 ++++++++ challenge-214/roger-bell-west/javascript/ch-2.js | 70 +++++++ challenge-214/roger-bell-west/kotlin/ch-1.kt | 58 +++++ challenge-214/roger-bell-west/kotlin/ch-2.kt | 73 +++++++ challenge-214/roger-bell-west/lua/ch-1.lua | 102 +++++++++ challenge-214/roger-bell-west/lua/ch-2.lua | 86 ++++++++ challenge-214/roger-bell-west/perl/ch-1.pl | 36 ++++ challenge-214/roger-bell-west/perl/ch-2.pl | 57 +++++ challenge-214/roger-bell-west/postscript/ch-1.ps | 256 +++++++++++++++++++++++ challenge-214/roger-bell-west/postscript/ch-2.ps | 178 ++++++++++++++++ challenge-214/roger-bell-west/python/ch-1.py | 44 ++++ challenge-214/roger-bell-west/python/ch-2.py | 53 +++++ challenge-214/roger-bell-west/raku/ch-1.p6 | 34 +++ challenge-214/roger-bell-west/raku/ch-2.p6 | 52 +++++ challenge-214/roger-bell-west/ruby/ch-1.rb | 51 +++++ challenge-214/roger-bell-west/ruby/ch-2.rb | 63 ++++++ challenge-214/roger-bell-west/rust/ch-1.rs | 54 +++++ challenge-214/roger-bell-west/rust/ch-2.rs | 65 ++++++ challenge-214/roger-bell-west/tests.yaml | 87 ++++++++ 19 files changed, 1507 insertions(+) create mode 100755 challenge-214/roger-bell-west/javascript/ch-1.js create mode 100755 challenge-214/roger-bell-west/javascript/ch-2.js create mode 100644 challenge-214/roger-bell-west/kotlin/ch-1.kt create mode 100644 challenge-214/roger-bell-west/kotlin/ch-2.kt create mode 100755 challenge-214/roger-bell-west/lua/ch-1.lua create mode 100755 challenge-214/roger-bell-west/lua/ch-2.lua create mode 100755 challenge-214/roger-bell-west/perl/ch-1.pl create mode 100755 challenge-214/roger-bell-west/perl/ch-2.pl create mode 100644 challenge-214/roger-bell-west/postscript/ch-1.ps create mode 100644 challenge-214/roger-bell-west/postscript/ch-2.ps create mode 100755 challenge-214/roger-bell-west/python/ch-1.py create mode 100755 challenge-214/roger-bell-west/python/ch-2.py create mode 100755 challenge-214/roger-bell-west/raku/ch-1.p6 create mode 100755 challenge-214/roger-bell-west/raku/ch-2.p6 create mode 100755 challenge-214/roger-bell-west/ruby/ch-1.rb create mode 100755 challenge-214/roger-bell-west/ruby/ch-2.rb create mode 100755 challenge-214/roger-bell-west/rust/ch-1.rs create mode 100755 challenge-214/roger-bell-west/rust/ch-2.rs create mode 100644 challenge-214/roger-bell-west/tests.yaml diff --git a/challenge-214/roger-bell-west/javascript/ch-1.js b/challenge-214/roger-bell-west/javascript/ch-1.js new file mode 100755 index 0000000000..01464b4ec2 --- /dev/null +++ b/challenge-214/roger-bell-west/javascript/ch-1.js @@ -0,0 +1,88 @@ +#! /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 rankscore(a) { + let av = new Map; + for (let s of a) { + if (av.has(s)) { + av.set(s, av.get(s) + 1); + } else { + av.set(s, 1); + } + } + let kk = Array.from(av.keys()); + kk.sort(function(a,b) { + return b-a; + }); + let rank = 1; + let tab = new Map; + for (let k of kk) { + const siz = av.get(k); + let r = ""; + if (rank <= 3) { + r = ["G", "S", "B"][rank - 1]; + } else { + r = rank.toString(); + } + if (siz > 1) { + r += "="; + } + tab.set(k, r); + rank += siz; + } + return a.map(i => tab.get(i)); +} + + +if (deepEqual(rankscore([1, 2, 4, 3, 5]), ['5', '4', 'S', 'B', 'G'])) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); +if (deepEqual(rankscore([8, 5, 6, 7, 4]), ['G', '4', 'B', 'S', '5'])) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); +if (deepEqual(rankscore([3, 5, 4, 2]), ['B', 'G', 'S', '4'])) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); +if (deepEqual(rankscore([2, 5, 2, 1, 7, 5, 1]), ['4=', 'S=', '4=', '6=', 'G', 'S=', '6='])) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write("\n"); diff --git a/challenge-214/roger-bell-west/javascript/ch-2.js b/challenge-214/roger-bell-west/javascript/ch-2.js new file mode 100755 index 0000000000..aabc5e43dc --- /dev/null +++ b/challenge-214/roger-bell-west/javascript/ch-2.js @@ -0,0 +1,70 @@ +#! /usr/bin/node + +"use strict" + +function collectpoints(a) { + let m = []; + let st = 0; + while (st < a.length) { + const k = a[st]; + let e = st; + while (e < a.length && a[e] == k) { + e += 1; + } + m.push([k, e - st]); + st = e; + } + let rv = 0; + let stack = [[m, 0]]; + while (stack.length > 0) { + const s = stack.pop(); + if (s[0].length == 0) { + rv = Math.max(rv, s[1]); + } else { + for (let i = 0; i < s[0].length; i++) { + let ss = JSON.parse(JSON.stringify(s)); + ss[1] += ss[0][i][1] * ss[0][i][1]; + ss[0].splice(i, 1); + let j = i; + while (true) { + if (j > 0 && + j < ss[0].length && + ss[0][j][0] == ss[0][j - 1][0]) { + ss[0][j][1] += ss[0][j - 1][1]; + ss[0].splice(j - 1, 1); + j -= 1; + } else { + break; + } + } + stack.push(ss); + } + } + } + return rv; +} + +if (collectpoints([2, 4, 3, 3, 3, 4, 5, 4, 2]) == 23) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); +if (collectpoints([1, 2, 2, 2, 2, 1]) == 20) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); +if (collectpoints([1]) == 1) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); +if (collectpoints([2, 2, 2, 1, 1, 2, 2, 2]) == 40) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write("\n"); diff --git a/challenge-214/roger-bell-west/kotlin/ch-1.kt b/challenge-214/roger-bell-west/kotlin/ch-1.kt new file mode 100644 index 0000000000..657c05c684 --- /dev/null +++ b/challenge-214/roger-bell-west/kotlin/ch-1.kt @@ -0,0 +1,58 @@ +fun rankscore(a: List): List { + var av = mutableMapOf() + for (s in a) { + if (av.contains(s)) { + av.put(s, av.get(s)!! + 1) + } else { + av.put(s, 1) + } + } + var kk = ArrayList(av.keys) + kk.sortWith(compareByDescending { it }) + var rank = 1 + var tab = mutableMapOf() + for (k in kk) { + val siz = av.get(k)!! + var r: String + if (rank <= 3) { + r = listOf("G", "S", "B")[rank - 1] + } else { + r = rank.toString() + } + if (siz > 1) { + r += "=" + } + tab.put(k, r) + rank += siz + } + return a.map {tab.get(it)!!}.toList() +} + +fun main() { + + if (rankscore(listOf(1, 2, 4, 3, 5)) == listOf("5", "4", "S", "B", "G")) { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (rankscore(listOf(8, 5, 6, 7, 4)) == listOf("G", "4", "B", "S", "5")) { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (rankscore(listOf(3, 5, 4, 2)) == listOf("B", "G", "S", "4")) { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (rankscore(listOf(2, 5, 2, 1, 7, 5, 1)) == listOf("4=", "S=", "4=", "6=", "G", "S=", "6=")) { + print("Pass") + } else { + print("Fail") + } + println("") + +} diff --git a/challenge-214/roger-bell-west/kotlin/ch-2.kt b/challenge-214/roger-bell-west/kotlin/ch-2.kt new file mode 100644 index 0000000000..b5941135f5 --- /dev/null +++ b/challenge-214/roger-bell-west/kotlin/ch-2.kt @@ -0,0 +1,73 @@ +import kotlin.math.max + +fun collectpoints(a: List): Int { + var m = ArrayList>() + var st = 0 + while (st < a.size) { + val k = a[st] + var e = st + while (e < a.size && a[e] == k) { + e += 1 + } + m.add(Pair(k, e - st)) + st = e + } + var rv = 0 + var stack = ArrayList>, Int>>() + stack.add(Pair(m, 0)) + while (stack.size > 0) { + val s = stack.removeLast() + if (s.first.size == 0) { + rv = max(rv, s.second) + } else { + for (i in 0 .. s.first.size - 1) { + var ss = Pair(ArrayList(s.first), s.second) + ss = Pair(ss.first, ss.second + ss.first[i].second * ss.first[i].second) + ss.first.removeAt(i) + var j = i + while (true) { + if (j >0 && + j < ss.first.size && + ss.first[j].first == ss.first[j - 1].first) { + ss.first[j] = Pair(ss.first[j].first, ss.first[j].second + ss.first[j - 1].second) + ss.first.removeAt(j - 1) + j -= 1 + } else { + break + } + } + stack.add(ss) + } + } + } + return rv +} + +fun main() { + + if (collectpoints(listOf(2, 4, 3, 3, 3, 4, 5, 4, 2)) == 23) { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (collectpoints(listOf(1, 2, 2, 2, 2, 1)) == 20) { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (collectpoints(listOf(1)) == 1) { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (collectpoints(listOf(2, 2, 2, 1, 1, 2, 2, 2)) == 40) { + print("Pass") + } else { + print("Fail") + } + println("") + +} diff --git a/challenge-214/roger-bell-west/lua/ch-1.lua b/challenge-214/roger-bell-west/lua/ch-1.lua new file mode 100755 index 0000000000..d656246e7d --- /dev/null +++ b/challenge-214/roger-bell-west/lua/ch-1.lua @@ -0,0 +1,102 @@ +#! /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 + +-- Roger's lualib +function keys(t) + local a = {} + for k, v in pairs(t) do + table.insert(a, k) + end + return a +end + +function rankscore(a) + local av = {} + for i, s in ipairs(a) do + if av[s] == nil then + av[s] = 1 + else + av[s] = av[s] + 1 + end + end + local kk = keys(av) + table.sort(kk, function (aa, bb) return bb < aa end) + local rank = 1 + local tab = {} + for i, k in ipairs(kk) do + local siz = av[k] + local r = "" + if rank <= 3 then + r = string.sub("GSB", rank, rank) + else + r = tostring(rank) + end + if siz > 1 then + r = r .. "=" + end + tab[k] = r + rank = rank + siz + end + local out = {} + for i, s in ipairs(a) do + table.insert(out, tab[s]) + end + return out +end + +if recursive_compare(rankscore({1, 2, 4, 3, 5}), {"5", "4", "S", "B", "G"}) then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if recursive_compare(rankscore({8, 5, 6, 7, 4}), {"G", "4", "B", "S", "5"}) then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if recursive_compare(rankscore({3, 5, 4, 2}), {"B", "G", "S", "4"}) then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if recursive_compare(rankscore({2, 5, 2, 1, 7, 5, 1}), {"4=", "S=", "4=", "6=", "G", "S=", "6="}) then + io.write("Pass") +else + io.write("FAIL") +end +print("") + diff --git a/challenge-214/roger-bell-west/lua/ch-2.lua b/challenge-214/roger-bell-west/lua/ch-2.lua new file mode 100755 index 0000000000..04a9cf7f6f --- /dev/null +++ b/challenge-214/roger-bell-west/lua/ch-2.lua @@ -0,0 +1,86 @@ +#! /usr/bin/lua + +-- from Roger's lualib +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 collectpoints(a) + local m = {} + local s = 1 + while s <= #a do + local k = a[s] + local e = s + while e <= #a and a[e] == k do + e = e + 1 + end + table.insert(m, {k, e - s}) + s = e + end + local rv = 0 + local stack = { { m, 0 } } + while #stack > 0 do + local s = table.remove(stack) + if #(s[1]) == 0 then + if rv < s[2] then + rv = s[2] + end + else + for i = 1, #(s[1]) do + local ss = deepcopy(s) + ss[2] = ss[2] + ss[1][i][2] * ss[1][i][2] + table.remove(ss[1], i) + j = i + while true do + if j > 1 and + j <= #(ss[1]) and + ss[1][j][1] == ss[1][j - 1][1] then + ss[1][j][2] = ss[1][j][2] + ss[1][j - 1][2] + table.remove(ss[1], j - 1) + j = j - 1 + else + break + end + end + table.insert(stack, ss) + end + end + end + return rv +end + +if collectpoints({2, 4, 3, 3, 3, 4, 5, 4, 2}) == 23 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if collectpoints({1, 2, 2, 2, 2, 1}) == 20 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if collectpoints({1}) == 1 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if collectpoints({2, 2, 2, 1, 1, 2, 2, 2}) == 40 then + io.write("Pass") +else + io.write("FAIL") +end +print("") + diff --git a/challenge-214/roger-bell-west/perl/ch-1.pl b/challenge-214/roger-bell-west/perl/ch-1.pl new file mode 100755 index 0000000000..1c27c6a80b --- /dev/null +++ b/challenge-214/roger-bell-west/perl/ch-1.pl @@ -0,0 +1,36 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use experimental 'signatures'; + +use Test::More tests => 4; + +is_deeply(rankscore([1, 2, 4, 3, 5]), ['5', '4', 'S', 'B', 'G'], 'example 1'); +is_deeply(rankscore([8, 5, 6, 7, 4]), ['G', '4', 'B', 'S', '5'], 'example 2'); +is_deeply(rankscore([3, 5, 4, 2]), ['B', 'G', 'S', '4'], 'example 3'); +is_deeply(rankscore([2, 5, 2, 1, 7, 5, 1]), ['4=', 'S=', '4=', '6=', 'G', 'S=', '6='], 'example 4'); + +sub rankscore($a) { + my %av; + foreach my $s (@{$a}) { + $av{$s}++; + } + my $rank = 1; + my %tab; + foreach my $k (sort {$::b <=> $::a} keys %av) { + my $siz = $av{$k}; + my $r; + if ($rank <= 3) { + $r = [qw(G S B)]->[$rank - 1]; + } else { + $r = $rank; + } + if ($siz > 1) { + $r .= "="; + } + $tab{$k} = $r; + $rank += $siz; + } + return [map {$tab{$_}} @{$a}]; +} diff --git a/challenge-214/roger-bell-west/perl/ch-2.pl b/challenge-214/roger-bell-west/perl/ch-2.pl new file mode 100755 index 0000000000..741c69ff65 --- /dev/null +++ b/challenge-214/roger-bell-west/perl/ch-2.pl @@ -0,0 +1,57 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use experimental 'signatures'; + +use Test::More tests => 4; + +is(collectpoints([2, 4, 3, 3, 3, 4, 5, 4, 2]), 23, 'example 1'); +is(collectpoints([1, 2, 2, 2, 2, 1]), 20, 'example 2'); +is(collectpoints([1]), 1, 'example 3'); +is(collectpoints([2, 2, 2, 1, 1, 2, 2, 2]), 40, 'example 4'); + +use Storable qw(dclone); +use List::Util qw(max); + +sub collectpoints($a) { + my @m; + my $s = 0; + while ($s <= $#{$a}) { + my $k = $a->[$s]; + my $e = $s; + while ($e <= $#{$a} && $a->[$e] == $k) { + $e++; + } + push @m,[$k, $e - $s]; + $s = $e; + } + my $rv = 0; + my @stack = ([\@m, 0]); + while (scalar @stack > 0) { + my $s = pop @stack; + if (scalar @{$s->[0]} == 0) { + $rv = max($rv, $s->[1]); + } else { + foreach my $i (0..$#{$s->[0]}) { + my $ss = dclone($s); + $ss->[1] += $ss->[0][$i][1] * $ss->[0][$i][1]; + splice @{$ss->[0]}, $i, 1; + my $j = $i; + while (1) { + if ($j > 0 && + $j < scalar @{$ss->[0]} && + $ss->[0][$j][0] == $ss->[0][$j-1][0]) { + $ss->[0][$j][1] += $ss->[0][$j-1][1]; + splice @{$ss->[0]}, $j - 1, 1; + $j--; + } else { + last; + } + } + push @stack, $ss; + } + } + } + return $rv; +} diff --git a/challenge-214/roger-bell-west/postscript/ch-1.ps b/challenge-214/roger-bell-west/postscript/ch-1.ps new file mode 100644 index 0000000000..3e2caf889f --- /dev/null +++ b/challenge-214/roger-bell-west/postscript/ch-1.ps @@ -0,0 +1,256 @@ +%!PS + +% begin included library code +% see https://codeberg.org/Firedrake/postscript-libraries/ +/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.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 { % [ a c b ] -> [ a b c ] + 1 dict begin + /arr exch def + arr length 0 gt { + 0 arr length 1 sub quicksort.main + } if + arr + end +} bind def + +/reverse { + 1 dict begin + dup length /l exch def + [ exch + aload pop + 2 1 l { + -1 roll + } for + ] + 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 + +/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 + +/safestring { + dup length string cvs +} 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 + +/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 + +/alloccvs { + 2 dict begin + /n exch def + /a 1 def + n + dup 0 lt { + /a a 1 add def + neg + } if + { + dup 10 lt { + exit + } if + /a a 1 add def + 10 idiv + } loop + pop + n a string cvs + end +} bind def + + +% end included library code + +/rankscore { + 8 dict begin + /a exch def + /av 0 dict def + a { + /s exch def + av s known { + av s av s get 1 add put + } { + av s 1 put + } ifelse + } forall + /rank 1 def + /tab 0 dict def + av keys quicksort reverse { + /k exch def + /siz av k get def + rank 3 le { + /r [ (G) (S) (B) ] rank 1 sub get def + } { + /r rank alloccvs def + } ifelse + siz 1 gt { + /s r length 1 add string def + r s copy + s r length (=) putinterval + /r s def + } if + tab k r safestring put + /rank rank siz add def + } forall + [ + a { + tab exch get + } forall + ] + end +} bind def + +(rankscore) test.start +[1 2 4 3 5] rankscore [(5) (4) (S) (B) (G)] deepeq test +[8 5 6 7 4] rankscore [(G) (4) (B) (S) (5)] deepeq test +[3 5 4 2] rankscore [(B) (G) (S) (4)] deepeq test +[2 5 2 1 7 5 1] rankscore [(4=) (S=) (4=) (6=) (G) (S=) (6=)] deepeq test +test.end diff --git a/challenge-214/roger-bell-west/postscript/ch-2.ps b/challenge-214/roger-bell-west/postscript/ch-2.ps new file mode 100644 index 0000000000..8cafbdd0e3 --- /dev/null +++ b/challenge-214/roger-bell-west/postscript/ch-2.ps @@ -0,0 +1,178 @@ +%!PS + +% begin included library code +% see https://codeberg.org/Firedrake/postscript-libraries/ +/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 + +/deepcopy { + 2 dict begin + /a exch def + a type /dicttype eq { + << + a keys { + /k exch get + 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 + +/apush.right { % [a b] c -> [a b c] + exch + [ exch aload length 2 add -1 roll ] +} bind def + +/apop.right { % [a b c] -> [a b] c + [ exch aload length 1 add 1 roll ] exch +} bind def + +/keys { % dict -> array of dict keys + [ exch + { + pop + } forall + ] +} bind def + +/remove { + 2 dict begin + /i exch def + aload length /l exch def + l i sub -1 roll pop + l 1 sub array astore + end +} 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 included library code + +/collectpoints { + 0 dict begin + /a exch def + /s 0 def + /m [ + { + s a length ge { + exit + } if + /k a s get def + /e s def + { + e a length ge { + exit + } if + a e get k ne { + exit + } if + /e e 1 add def + } loop + [ k e s sub ] + /s e def + } loop + ] def + /rv 0 def + /stack [ [ m 0 ] ] def + { + stack length 0 eq { + exit + } if + stack apop.right /s exch def /stack exch def + s 0 get length 0 eq { + /rv rv s 1 get max def + } { + 0 1 s 0 get length 1 sub { + /i exch def + /ss s deepcopy def + ss 1 ss 1 get ss 0 get i get 1 get dup mul add put + ss 0 ss 0 get i remove put + { + /ex true def + i 1 add ss 0 get length lt { + ss 0 get i get 0 get ss 0 get i 1 add get 0 get eq { + ss 0 get i get 1 + ss 0 get i get 1 get + ss 0 get i 1 add get 1 get + add + put + ss 0 + ss 0 get i 1 add remove + put + /ex false def + } if + } if + ex { + i 0 gt i ss 0 get length lt and { + ss 0 get i get 0 get ss 0 get i 1 sub get 0 get eq { + ss 0 get i get 1 + ss 0 get i get 1 get ss 0 get i 1 sub get 1 get add + put + ss 0 + ss 0 get i 1 sub remove + put + /ex false def + } if + } if + } if + ex { + exit + } if + } loop + /stack stack ss apush.right def + } for + } ifelse + } loop + rv + end +} bind def + +(collectpoints) test.start +[2 4 3 3 3 4 5 4 2] collectpoints 23 eq test +[1 2 2 2 2 1] collectpoints 20 eq test +[1] collectpoints 1 eq test +[2 2 2 1 1 2 2 2] collectpoints 40 eq test +test.end diff --git a/challenge-214/roger-bell-west/python/ch-1.py b/challenge-214/roger-bell-west/python/ch-1.py new file mode 100755 index 0000000000..7eaa04b4f5 --- /dev/null +++ b/challenge-214/roger-bell-west/python/ch-1.py @@ -0,0 +1,44 @@ +#! /usr/bin/python3 + +import unittest + +def rankscore(a): + av = dict() + for s in a: + if s in av: + av[s] += 1 + else: + av[s] = 1 + kk = list(av.keys()) + kk.sort() + kk.reverse() + rank = 1 + tab = dict() + for k in kk: + siz = av[k] + r = "" + if rank <= 3: + r = ["G", "S", "B"][rank - 1] + else: + r = str(rank) + if siz > 1: + r += "=" + tab[k] = r + rank += siz + return [tab[i] for i in a] + +class TestRankscore(unittest.TestCase): + + def test_ex1(self): + self.assertEqual(rankscore([1, 2, 4, 3, 5]), ["5", "4", "S", "B", "G"], 'example 1') + + def test_ex2(self): + self.assertEqual(rankscore([8, 5, 6, 7, 4]), ["G", "4", "B", "S", "5"], 'example 2') + + def test_ex3(self): + self.assertEqual(rankscore([3, 5, 4, 2]), ["B", "G", "S", "4"], 'example 3') + + def test_ex4(self): + self.assertEqual(rankscore([2, 5, 2, 1, 7, 5, 1]), ["4=", "S=", "4=", "6=", "G", "S=", "6="], 'example 4') + +unittest.main() diff --git a/challenge-214/roger-bell-west/python/ch-2.py b/challenge-214/roger-bell-west/python/ch-2.py new file mode 100755 index 0000000000..bb5f35509a --- /dev/null +++ b/challenge-214/roger-bell-west/python/ch-2.py @@ -0,0 +1,53 @@ +#! /usr/bin/python3 + +from copy import deepcopy + +def collectpoints(a): + m = [] + st = 0 + while st < len(a): + k = a[st] + e = st + while e < len(a) and a[e] == k: + e += 1 + m.append([k, e - st]) + st = e + rv = 0 + stack = [[m, 0]] + while len(stack) > 0: + s = stack.pop() + if len(s[0]) == 0: + rv = max(rv, s[1]) + else: + for i in range(len(s[0])): + ss = deepcopy(s) + ss[1] += ss[0][i][1] * ss[0][i][1] + del ss[0][i] + j = i + while True: + if j > 0 and j < len(ss[0]) and ss[0][j][0] == ss[0][j - 1][0]: + ss[0][j][1] += ss[0][j - 1][1] + del ss[0][j - 1] + j -= 1 + else: + break + stack.append(ss) + return rv + +import unittest + +class TestCollectpoints(unittest.TestCase): + + def test_ex1(self): + self.assertEqual(collectpoints([2, 4, 3, 3, 3, 4, 5, 4, 2]), 23, 'example 1') + + def test_ex2(self): + self.assertEqual(collectpoints([1, 2, 2, 2, 2, 1]), 20, 'example 2') + + def test_ex3(self): + self.assertEqual(collectpoints([1]), 1, 'example 3') + + def test_ex4(self): + self.assertEqual(collectpoints([2, 2, 2, 1, 1, 2, 2, 2]), 40, 'example 4') + +unittest.main() diff --git a/challenge-214/roger-bell-west/raku/ch-1.p6 b/challenge-214/roger-bell-west/raku/ch-1.p6 new file mode 100755 index 0000000000..dcc445b194 --- /dev/null +++ b/challenge-214/roger-bell-west/raku/ch-1.p6 @@ -0,0 +1,34 @@ +#! /usr/bin/raku + +use Test; + +plan 4; + +is-deeply(rankscore([1, 2, 4, 3, 5]), ['5', '4', 'S', 'B', 'G'], 'example 1'); +is-deeply(rankscore([8, 5, 6, 7, 4]), ['G', '4', 'B', 'S', '5'], 'example 2'); +is-deeply(rankscore([3, 5, 4, 2]), ['B', 'G', 'S', '4'], 'example 3'); +is-deeply(rankscore([2, 5, 2, 1, 7, 5, 1]), ['4=', 'S=', '4=', '6=', 'G', 'S=', '6='], 'example 4'); + +sub rankscore(@a) { + my %av; + for @a -> $s { + %av{$s}++; + } + my $rank = 1; + my %tab; + for (sort {$^b <=> $^a}, %av.keys) -> $k { + my $siz = %av{$k}; + my $r; + if ($rank <= 3) { + $r = ['G', 'S', 'B'][$rank - 1]; + } else { + $r = '' ~ $rank; + } + if ($siz > 1) { + $r ~= "="; + } + %tab{$k} = $r; + $rank += $siz; + } + return [map {%tab{$_}}, @a]; +} diff --git a/challenge-214/roger-bell-west/raku/ch-2.p6 b/challenge-214/roger-bell-west/raku/ch-2.p6 new file mode 100755 index 0000000000..045c73d02c --- /dev/null +++ b/challenge-214/roger-bell-west/raku/ch-2.p6 @@ -0,0 +1,52 @@ +#! /usr/bin/raku + +use Test; + +plan 4; + +is(collectpoints([2, 4, 3, 3, 3, 4, 5, 4, 2]), 23, 'example 1'); +is(collectpoints([1, 2, 2, 2, 2, 1]), 20, 'example 2'); +is(collectpoints([1]), 1, 'example 3'); +is(collectpoints([2, 2, 2, 1, 1, 2, 2, 2]), 40, 'example 4'); + +sub collectpoints(@a) { + my @m; + my $s = 0; + while ($s < @a.elems) { + my $k = @a[$s]; + my $e = $s; + while ($e < @a.elems && @a[$e] == $k) { + $e++; + } + @m.push([$k, $e - $s]); + $s = $e; + } + my $rv = 0; + my @stack = [[@m, 0], ]; + while (@stack.elems > 0) { + my @s = @stack.pop.List; + if (@s[0].elems == 0) { + $rv = max($rv, @s[1]); + } else { + for (0..@s[0].end) -> $i { + my @ss = [@s[0].map({[$_.[0], $_.[1]]}).Array, @s[1]]; + @ss[1] += @ss[0][$i][1] * @ss[0][$i][1]; + splice @ss[0], $i, 1; + my $j = $i; + while (True) { + if ($j > 0 && + $j < @ss[0].elems && + @ss[0][$j][0] == @ss[0][$j-1][0]) { + @ss[0][$j][1] += @ss[0][$j-1][1]; + splice @ss[0], $j - 1, 1; + $j--; + } else { + last; + } + } + @stack.push(@ss); + } + } + } + return $rv; +} diff --git a/challenge-214/roger-bell-west/ruby/ch-1.rb b/challenge-214/roger-bell-west/ruby/ch-1.rb new file mode 100755 index 0000000000..4ee7f8f176 --- /dev/null +++ b/challenge-214/roger-bell-west/ruby/ch-1.rb @@ -0,0 +1,51 @@ +#! /usr/bin/ruby + +require 'test/unit' + +def rankscore(a) + av = Hash.new + a.each do |s| + if av.has_key?(s) then + av[s] += 1 + else + av[s] = 1 + end + end + rank = 1 + tab = Hash.new + av.keys.sort.reverse.each do |k| + siz = av[k] + r = "" + if rank <= 3 then + r = ["G", "S", "B"][rank - 1] + else + r = rank.to_s + end + if siz > 1 then + r += "=" + end + tab[k] = r + rank += siz + end + return a.map{|i| tab[i]} +end + +class TestRankscore < Test::Unit::TestCase + + def test_ex1 + assert_equal(['5', '4', 'S', 'B', 'G'], rankscore([1, 2, 4, 3, 5])) + end + + def test_ex2 + assert_equal(['G', '4', 'B', 'S', '5'], rankscore([8, 5, 6, 7, 4])) + end + + def test_ex3 + assert_equal(['B', 'G', 'S', '4'], rankscore([3, 5, 4, 2])) + end + + def test_ex4 + assert_equal(['4=', 'S=', '4=', '6=', 'G', 'S=', '6='], rankscore([2, 5, 2, 1, 7, 5, 1])) + end + +end diff --git a/challenge-214/roger-bell-west/ruby/ch-2.rb b/challenge-214/roger-bell-west/ruby/ch-2.rb new file mode 100755 index 0000000000..377e37d24a --- /dev/null +++ b/challenge-214/roger-bell-west/ruby/ch-2.rb @@ -0,0 +1,63 @@ +#! /usr/bin/ruby + +def collectpoints(a) + m = [] + s = 0 + while s < a.length do + k = a[s] + e = s + while e < a.length && a[e] == k do + e += 1 + end + m.push([k, e - s]) + s = e + end + rv = 0 + stack = [[m, 0]] + while stack.length > 0 do + s = stack.pop + if s[0].length == 0 then + rv = [rv, s[1]].max + else + 0.upto(s[0].length - 1) do |i| + ss = Marshal.load(Marshal.dump(s)) + ss[1] += ss[0][i][1] * ss[0][i][1] + ss[0].delete_at(i) + j = i + while true do + if j > 0 && j < ss[0].length && ss[0][j][0] == ss[0][j-1][0] then + ss[0][j][1] += ss[0][j-1][1] + ss[0].delete_at(j - 1) + j -= 1 + else + break + end + end + stack.push(ss) + end + end + end + return rv +end + +require 'test/unit' + +class TestCollectpoints < Test::Unit::TestCase + + def test_ex1 + assert_equal(23, collectpoints([2, 4, 3, 3, 3, 4, 5, 4, 2])) + end + + def test_ex2 + assert_equal(20, collectpoints([1, 2, 2, 2, 2, 1])) + end + + def test_ex3 + assert_equal(1, collectpoints([1])) + end + + def test_ex4 + assert_equal(40, collectpoints([2, 2, 2, 1, 1, 2, 2, 2])) + end + +end diff --git a/challenge-214/roger-bell-west/rust/ch-1.rs b/challenge-214/roger-bell-west/rust/ch-1.rs new file mode 100755 index 0000000000..8722bfe41a --- /dev/null +++ b/challenge-214/roger-bell-west/rust/ch-1.rs @@ -0,0 +1,54 @@ +#! /bin/sh +//usr/bin/env rustc --test $0 -o ${0}x && ./${0}x --nocapture; rm -f ${0}x ; exit + +use std::collections::HashMap; + +#[test] +fn test_ex1() { + assert_eq!(rankscore(vec![1, 2, 4, 3, 5]), vec!["5", "4", "S", "B", "G"]); +} + +#[test] +fn test_ex2() { + assert_eq!(rankscore(vec![8, 5, 6, 7, 4]), vec!["G", "4", "B", "S", "5"]); +} + +#[test] +fn test_ex3() { + assert_eq!(rankscore(vec![3, 5, 4, 2]), vec!["B", "G", "S", "4"]); +} + +#[test] +fn test_ex4() { + assert_eq!( + rankscore(vec![2, 5, 2, 1, 7, 5, 1]), + vec!["4=", "S=", "4=", "6=", "G", "S=", "6="] + ); +} + +fn rankscore(a: Vec) -> Vec { + let mut av: HashMap = HashMap::new(); + for s in &a { + av.entry(*s).and_modify(|k| *k += 1).or_insert(1); + } + let mut kk = av.keys().collect::>(); + kk.sort_unstable(); + kk.reverse(); + let mut rank = 1; + let mut tab: HashMap = HashMap::new(); + for k in kk { + let siz = av.get(k).unwrap(); + let mut r: String; + if rank <= 3 { + r = ["G", "S", "B"][rank - 1].to_string(); + } else { + r = rank.to_string(); + }; + if *siz > 1 { + r.push('='); + } + tab.insert(*k, r.to_string()); + rank += siz; + } + a.iter().map(|i| tab.get(i).unwrap().to_string()).collect::>() +} diff --git a/challenge-214/roger-bell-west/rust/ch-2.rs b/challenge-214/roger-bell-west/rust/ch-2.rs new file mode 100755 index 0000000000..b23c94c698 --- /dev/null +++ b/challenge-214/roger-bell-west/rust/ch-2.rs @@ -0,0 +1,65 @@ +#! /bin/sh +//usr/bin/env rustc --test $0 -o ${0}x && ./${0}x --nocapture; rm -f ${0}x ; exit + +use std::cmp::max; + +#[test] +fn test_ex1() { + assert_eq!(collectpoints(vec![2, 4, 3, 3, 3, 4, 5, 4, 2]), 23); +} + +#[test] +fn test_ex2() { + assert_eq!(collectpoints(vec![1, 2, 2, 2, 2, 1]), 20); +} + +#[test] +fn test_ex3() { + assert_eq!(collectpoints(vec![1]), 1); +} + +#[test] +fn test_ex4() { + assert_eq!(collectpoints(vec![2, 2, 2, 1, 1, 2, 2, 2]), 40); +} + +fn collectpoints(a: Vec) -> u32 { + let mut m: Vec<(i32, u32)> = Vec::new(); + let mut s = 0; + while s < a.len() { + let k = a[s]; + let mut e = s; + while e < a.len() && a[e] == k { + e += 1; + } + m.push((k, (e - s) as u32)); + s = e; + } + let mut rv = 0; + let mut stack: Vec<(Vec<(i32, u32)>, u32)> = Vec::new(); + stack.push((m, 0)); + while stack.len() > 0 { + let s = stack.pop().unwrap(); + if s.0.len() == 0 { + rv = max(rv, s.1); + } else { + for i in 0..s.0.len() { + let mut ss = s.clone(); + ss.1 += ss.0[i].1 * ss.0[i].1; + ss.0.remove(i); + let mut j = i; + loop { + if j > 0 && j < ss.0.len() && ss.0[j].0 == ss.0[j - 1].0 { + ss.0[j].1 += ss.0[j - 1].1; + ss.0.remove(j - 1); + j -= 1; + } else { + break; + } + } + stack.push(ss); + } + } + } + rv +} diff --git a/challenge-214/roger-bell-west/tests.yaml b/challenge-214/roger-bell-west/tests.yaml new file mode 100644 index 0000000000..b077710310 --- /dev/null +++ b/challenge-214/roger-bell-west/tests.yaml @@ -0,0 +1,87 @@ +--- +ch-1: + - function: rankscore + arguments: + - 1 + - 2 + - 4 + - 3 + - 5 + result: + - "5" + - "4" + - "S" + - "B" + - "G" + - arguments: + - 8 + - 5 + - 6 + - 7 + - 4 + result: + - "G" + - "4" + - "B" + - "S" + - "5" + - arguments: + - 3 + - 5 + - 4 + - 2 + result: + - "B" + - "G" + - "S" + - "4" + - arguments: + - 2 + - 5 + - 2 + - 1 + - 7 + - 5 + - 1 + result: + - "4=" + - "S=" + - "4=" + - "6=" + - "G" + - "S=" + - "6=" +ch-2: + - function: collectpoints + arguments: + - 2 + - 4 + - 3 + - 3 + - 3 + - 4 + - 5 + - 4 + - 2 + result: 23 + - arguments: + - 1 + - 2 + - 2 + - 2 + - 2 + - 1 + result: 20 + - arguments: + - 1 + result: 1 + - arguments: + - 2 + - 2 + - 2 + - 1 + - 1 + - 2 + - 2 + - 2 + result: 40 -- cgit