From bff4843d39dd97ab2b8616da4c32e67438148744 Mon Sep 17 00:00:00 2001 From: Roger Bell_West Date: Mon, 23 May 2022 09:12:11 +0100 Subject: Solutions for challenge #166 --- challenge-166/roger-bell-west/javascript/ch-1.js | 134 ++++++++++++ challenge-166/roger-bell-west/javascript/ch-2.js | 59 +++++ challenge-166/roger-bell-west/kotlin/ch-1.kt | 133 ++++++++++++ challenge-166/roger-bell-west/kotlin/ch-2.kt | 55 +++++ challenge-166/roger-bell-west/lua/ch-1.lua | 144 +++++++++++++ challenge-166/roger-bell-west/perl/ch-1.pl | 98 +++++++++ challenge-166/roger-bell-west/perl/ch-2.pl | 59 +++++ challenge-166/roger-bell-west/postscript/ch-1.ps | 263 +++++++++++++++++++++++ challenge-166/roger-bell-west/postscript/ch-2.ps | 206 ++++++++++++++++++ challenge-166/roger-bell-west/python/ch-1.py | 87 ++++++++ challenge-166/roger-bell-west/python/ch-2.py | 39 ++++ challenge-166/roger-bell-west/raku/ch-1.p6 | 79 +++++++ challenge-166/roger-bell-west/raku/ch-2.p6 | 51 +++++ challenge-166/roger-bell-west/ruby/ch-1.rb | 103 +++++++++ challenge-166/roger-bell-west/ruby/ch-2.rb | 54 +++++ challenge-166/roger-bell-west/rust/ch-1.rs | 97 +++++++++ challenge-166/roger-bell-west/rust/ch-2.rs | 75 +++++++ 17 files changed, 1736 insertions(+) create mode 100755 challenge-166/roger-bell-west/javascript/ch-1.js create mode 100755 challenge-166/roger-bell-west/javascript/ch-2.js create mode 100644 challenge-166/roger-bell-west/kotlin/ch-1.kt create mode 100644 challenge-166/roger-bell-west/kotlin/ch-2.kt create mode 100755 challenge-166/roger-bell-west/lua/ch-1.lua create mode 100755 challenge-166/roger-bell-west/perl/ch-1.pl create mode 100755 challenge-166/roger-bell-west/perl/ch-2.pl create mode 100644 challenge-166/roger-bell-west/postscript/ch-1.ps create mode 100644 challenge-166/roger-bell-west/postscript/ch-2.ps create mode 100755 challenge-166/roger-bell-west/python/ch-1.py create mode 100755 challenge-166/roger-bell-west/python/ch-2.py create mode 100755 challenge-166/roger-bell-west/raku/ch-1.p6 create mode 100755 challenge-166/roger-bell-west/raku/ch-2.p6 create mode 100755 challenge-166/roger-bell-west/ruby/ch-1.rb create mode 100755 challenge-166/roger-bell-west/ruby/ch-2.rb create mode 100644 challenge-166/roger-bell-west/rust/ch-1.rs create mode 100755 challenge-166/roger-bell-west/rust/ch-2.rs diff --git a/challenge-166/roger-bell-west/javascript/ch-1.js b/challenge-166/roger-bell-west/javascript/ch-1.js new file mode 100755 index 0000000000..6e8f662d3a --- /dev/null +++ b/challenge-166/roger-bell-west/javascript/ch-1.js @@ -0,0 +1,134 @@ +#! /usr/bin/node + +function hexwords(lo,hi,sb) { + const fs = require("fs") + let out = [] + let buffer = fs.readFileSync("dictionary.txt","utf8") + buffer.split(/\r?\n/).forEach(line => { + if (line.length >= lo && line.length <= hi) { + let valid = true + let sbc = 0 + for (let c of line.split("") ) { + if (c == 'o' || c == 'i' || c == 'l' || c == 's' || c == 't') { + sbc++ + if (sbc > sb) { + valid = false + } + } else if (c < 'a' || c > 'f') { + valid = false + } + if (!valid) { + break + } + } + if (valid) { + out.push(line) + } + } + }) + return out +} + +function combiwords(wl,l) { + let wh = new Map() + for (let w of wl) { + let lw = w.length + if (!wh.has(lw)) { + wh.set(lw,[]) + } + let t = wh.get(lw) + t.push(w) + wh.set(lw,t) + } + let tmap = [[]] + let omap = [] + while (tmap.length > 0) { + let c = tmap.pop() + let s = c.reduce((x,y) => x+y, 0) + for (let j=1; j < l-s; j++) { + if (wh.has(j)) { + let cc = [...c] + cc.push(j) + tmap.push(cc) + } + } + if (wh.has(l-s)) { + c.push(l-s) + omap.push(c) + } + } + let out = [] + for (let pat of omap) { + let c = [] + let cm = [] + for (let i of pat) { + cm.push(wh.get(i).length-1) + c.push(0) + } + let ex = false + while (!ex) { + let o = [] + for (let i = 0; i < c.length; i++) { + o.push(wh.get(pat[i])[c[i]]) + } + out.push(o.join("")) + let ss = c.length-1 + while (true) { + c[ss]++ + if (c[ss] > cm[ss]) { + if (ss == 0) { + ex = true + break + } + c[ss] = 0 + ss-- + } else { + break + } + } + } + } + return out +} + +if (hexwords(2,8,8).length == 1463) { + process.stdout.write("Pass") +} else { + process.stdout.write("FAIL") +} +process.stdout.write(" "); + +if (hexwords(8,8,8).length == 164) { + process.stdout.write("Pass") +} else { + process.stdout.write("FAIL") +} +process.stdout.write(" "); + +if (hexwords(2,8,0).length == 45) { + process.stdout.write("Pass") +} else { + process.stdout.write("FAIL") +} +process.stdout.write(" "); + +if (hexwords(2,8,1).length == 244) { + process.stdout.write("Pass") +} else { + process.stdout.write("FAIL") +} +process.stdout.write(" "); + +if (combiwords(hexwords(4,4,0),8).length == 144) { + process.stdout.write("Pass") +} else { + process.stdout.write("FAIL") +} +process.stdout.write(" "); + +if (combiwords(hexwords(3,5,0),8).length == 274) { + process.stdout.write("Pass") +} else { + process.stdout.write("FAIL") +} +process.stdout.write("\n"); diff --git a/challenge-166/roger-bell-west/javascript/ch-2.js b/challenge-166/roger-bell-west/javascript/ch-2.js new file mode 100755 index 0000000000..7380afa1e0 --- /dev/null +++ b/challenge-166/roger-bell-west/javascript/ch-2.js @@ -0,0 +1,59 @@ +#! /usr/bin/node + +function kdd(dirlist0) { + const fs = require("fs") + let dirlist = Array.from(dirlist0) + dirlist.sort() + let fx = new Map() + for (let d of dirlist) { + for (let entry of fs.readdirSync(d, { withFileTypes: true })) { + let nn = entry.name + if (entry.isDirectory()) { + nn += "/" + } + if (!fx.has(nn)) { + fx.set(nn,new Set()) + } + let t = fx.get(nn) + t.add(d) + fx.set(nn,t) + } + } + let mm = dirlist.length + let out = [dirlist] + for (let f of [...fx.keys()].sort()) { + if (fx.get(f).size != mm) { + let l = [] + for (let d of dirlist) { + if (fx.get(f).has(d)) { + l.push(f) + } else { + l.push("") + } + } + out.push(l) + } + } + tabular(out) +} + +function tabular(d) { + let columnlength = [] + d.forEach(row => { + row.forEach((col, i) => { + while (columnlength.length <= i) { + columnlength.push(0) + } + columnlength[i] = Math.max(columnlength[i], col.length) + }) + }) + d.forEach(row => { + let s = [] + row.forEach((col, i) => { + s.push(col.padEnd(columnlength[i])) + }) + console.log(s.join(" | ")) + }) +} + +kdd(["dir_a","dir_b","dir_c"]) diff --git a/challenge-166/roger-bell-west/kotlin/ch-1.kt b/challenge-166/roger-bell-west/kotlin/ch-1.kt new file mode 100644 index 0000000000..c391716661 --- /dev/null +++ b/challenge-166/roger-bell-west/kotlin/ch-1.kt @@ -0,0 +1,133 @@ +import kotlin.io.* + +fun hexwords(lo: Int, hi: Int, sb: Int): List { + var out = ArrayList() + java.io.File("dictionary.txt").forEachLine { line -> + if (line.length >= lo && line.length <= hi) { + var valid = true + var sbc = 0 + for (c in line.toCharArray().toList()) { + if (c == 'o' || c == 'i' || c == 'l' || c == 's' || c == 't') { + sbc += 1 + if (sbc > sb) { + valid = false + } + } else if (c < 'a' || c > 'f') { + valid = false + } + if (!valid) { + break + } + } + if (valid) { + out.add(line) + } + } + } + return out +} + +fun combiwords(wl: List, l: Int): List { + var wh = mutableMapOf>() + for (w in wl) { + if (!wh.containsKey(w.length)) { + wh[w.length] = ArrayList() + } + wh[w.length]!!.add(w) + } + var tmap = ArrayList>() + tmap.add(ArrayList()) + var omap = ArrayList>() + while (tmap.size > 0) { + var c = tmap.removeLast() + val s = c.sum() + val ls = l - s + for (j in 1..ls-1) { + if (wh.containsKey(j)) { + var cc = ArrayList(c) + cc.add(j) + tmap.add(cc) + } + } + if (wh.containsKey(ls)) { + c.add(ls) + omap.add(c) + } + } + var out = ArrayList() + for (pat in omap) { + var c = ArrayList() + var cm = ArrayList() + for (i in pat) { + cm.add(wh[i]!!.size-1) + c.add(0) + } + var ex = false + while (!ex) { + var o = ArrayList() + for (i in 0..c.size-1) { + o.add(wh[pat[i]]!![c[i]]) + } + out.add(o.joinToString("")) + var ss = c.size-1 + while (true) { + c[ss] += 1 + if (c[ss] > cm[ss]) { + if (ss == 0) { + ex = true + break + } + c[ss] = 0 + ss-- + } else { + break + } + } + } + } + return out +} + +fun main() { + if (hexwords(2,8,8).size == 1463) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + + if (hexwords(8,8,8).size == 164) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + + if (hexwords(2,8,0).size == 45) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + + if (hexwords(2,8,1).size == 244) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + + if (combiwords(hexwords(4,4,0),8).size == 144) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + + if (combiwords(hexwords(3,5,0),8).size == 274) { + print("Pass") + } else { + print("FAIL") + } + println("") +} diff --git a/challenge-166/roger-bell-west/kotlin/ch-2.kt b/challenge-166/roger-bell-west/kotlin/ch-2.kt new file mode 100644 index 0000000000..b69f6eb44f --- /dev/null +++ b/challenge-166/roger-bell-west/kotlin/ch-2.kt @@ -0,0 +1,55 @@ +import kotlin.io.* +import kotlin.math.max + +fun kdd(dirlist0: ArrayList): ArrayList> { + val dirlist = ArrayList(dirlist0.sorted()) + var fx = mutableMapOf>() + for (d in dirlist) { + java.io.File(d).listFiles().forEach() { entry -> + var nn = entry.getName() + if (entry.isDirectory()) { + nn += "/" + } + if (!fx.containsKey(nn)) { + fx[nn] = mutableSetOf() + } + fx[nn]!!.add(d) + } + } + val mm = dirlist.size + var out = arrayListOf(dirlist) + for (f in fx.keys.sorted()) { + if (fx[f]!!.size != mm) { + var l = arrayListOf() + for (d in dirlist) { + if (fx[f]!!.contains(d)) { + l.add(f) + } else { + l.add("") + } + } + out.add(l) + } + } + return(out) +} + +fun tabular(d: ArrayList>) { + var columnlength = ArrayList() + for (row in d) { + row.forEachIndexed {i,col -> + while (columnlength.size <= i) { + columnlength.add(0) + } + columnlength[i] = max(columnlength[i],col.length) + } + } + val fstr=columnlength.map {l -> "%-" + l.toString() + "s"}.joinToString(" | ") + for (row in d) { + println(fstr.format(*row.toTypedArray())) + } +} + +fun main() { + tabular(kdd(arrayListOf("dir_a","dir_b","dir_c"))) +} diff --git a/challenge-166/roger-bell-west/lua/ch-1.lua b/challenge-166/roger-bell-west/lua/ch-1.lua new file mode 100755 index 0000000000..4b7858db3c --- /dev/null +++ b/challenge-166/roger-bell-west/lua/ch-1.lua @@ -0,0 +1,144 @@ +#! /usr/bin/lua + +function join(t) + local out="" + for k,v in pairs(t) do + out = out .. v + end + return out +end + +function hexwords(lo,hi,sb) + local out = {} + for line in io.lines("dictionary.txt") do + if #line >= lo and #line <= hi then + local valid = true + local sbc = 0 + for i = 1,#line do + local c = string.sub(line,i,i) + if c == "o" or c == "i" or c == "l" or c == "s" or c == "t" then + sbc = sbc + 1 + if sbc > sb then + valid = false + end + elseif c < "a" or c > "f" then + valid = false + end + if not valid then + break + end + end + if valid then + table.insert(out,line) + end + end + end + return out +end + +function combiwords(wl,l) + local wh = {} + for k,w in pairs(wl) do + if wh[#w] == nil then + wh[#w] = {} + end + table.insert(wh[#w],w) + end + local tmap = { {} } + local omap = {} + while #tmap > 0 do + local c = table.remove(tmap) + local s = 0 + for k,x in pairs(c) do + s = s + x + end + for j = 1, l-s-1 do + if wh[j] ~= nil then + local cc = {} + for k,x in pairs(c) do + table.insert(cc,x) + end + table.insert(cc,j) + table.insert(tmap,cc) + end + end + if wh[l-s] ~= nil then + table.insert(c,l-s) + table.insert(omap,c) + end + end + local out = {} + for k,pat in pairs(omap) do + local c = {} + local cm = {} + for kk,i in pairs(pat) do + table.insert(cm,#wh[i]) + table.insert(c,1) + end + local ex = false + while not ex do + local o = {} + for i = 1,#c do + table.insert(o,wh[pat[i]][c[i]]) + end + table.insert(out,join(o,"")) + local ss = #c + while true do + c[ss] = c[ss] + 1 + if c[ss] > cm[ss] then + if ss == 1 then + ex = true + break + end + c[ss] = 1 + ss = ss - 1 + else + break + end + end + end + end + return out +end + +if #hexwords(2,8,8) == 1463 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if #hexwords(8,8,8) == 164 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if #hexwords(2,8,0) == 45 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if #hexwords(2,8,1) == 244 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if #combiwords(hexwords(4,4,0),8) == 144 then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if #combiwords(hexwords(3,5,0),8) == 274 then + io.write("Pass") +else + io.write("FAIL") +end +print("") diff --git a/challenge-166/roger-bell-west/perl/ch-1.pl b/challenge-166/roger-bell-west/perl/ch-1.pl new file mode 100755 index 0000000000..a87a976310 --- /dev/null +++ b/challenge-166/roger-bell-west/perl/ch-1.pl @@ -0,0 +1,98 @@ +#! /usr/bin/perl + +use strict; +use warnings; + +use experimental 'signatures'; + +use List::Util qw(sum0); + +use Test::More tests => 6; + +is(scalar @{hexwords(2,8,8)},1463,'example 1'); + +is(scalar @{hexwords(8,8,8)},164,'example 2'); + +is(scalar @{hexwords(2,8,0)},45,'example 3'); + +is(scalar @{hexwords(2,8,1)},244,'example 4'); + +is(scalar @{combiwords(hexwords(4,4,0),8)},144,'example 5'); + +is(scalar @{combiwords(hexwords(3,5,0),8)},274,'example 6'); + +sub hexwords($lo,$hi,$sb) { + my @out; + open my $fh,'<','dictionary.txt'; + while (my $line = <$fh>) { + chomp $line; + if (length($line) >= $lo && length($line) <= $hi) { + my $valid = 1; + my $sbc = 0; + foreach my $c (split '',$line) { + if ($c =~ /[oilst]/) { + $sbc++; + if ($sbc > $sb) { + $valid = 0; + } + } elsif ($c lt 'a' || $c gt 'f') { + $valid = 0; + } + unless ($valid) { + last; + } + } + if ($valid) { + push @out,$line; + } + } + } + close $fh; + return \@out; +} + +sub combiwords($wl,$l) { + my %wh; + foreach my $w (@{$wl}) { + push @{$wh{length($w)}},$w; + } + my @tmap=([]); + my @omap; + while (scalar @tmap > 0) { + my $c=pop @tmap; + my $s=sum0(@{$c}); + my $ls=$l-$s; + foreach my $j (1..$ls-1) { + if (exists $wh{$j}) { + push @tmap,[@{$c},$j]; + } + } + if (exists $wh{$ls}) { + push @omap,[@{$c},$ls]; + } + } + my @out; + foreach my $pat (@omap) { + my @c = (0) x (scalar @{$pat}); + my @cm = map {scalar @{$wh{$pat->[$_]}}-1} (0..$#c); + my $ex = 0; + while (!$ex) { + push @out,join('',map {$wh{$pat->[$_]}->[$c[$_]]} (0..$#c)); + my $ss = $#c; + while (1) { + $c[$ss]++; + if ($c[$ss] > $cm[$ss]) { + if ($ss == 0) { + $ex = 1; + last; + } + $c[$ss] = 0; + $ss--; + } else { + last; + } + } + } + } + return \@out; +} diff --git a/challenge-166/roger-bell-west/perl/ch-2.pl b/challenge-166/roger-bell-west/perl/ch-2.pl new file mode 100755 index 0000000000..d5e7ea52e6 --- /dev/null +++ b/challenge-166/roger-bell-west/perl/ch-2.pl @@ -0,0 +1,59 @@ +#! /usr/bin/perl + +use strict; +use warnings; + +use experimental 'signatures'; + +sub kdd(@dirlist0) { + my @dirlist = sort @dirlist0; + my %fx; + foreach my $d (@dirlist) { + opendir (my $dh,$d); + foreach my $entry (grep !/^\./,readdir $dh) { + my $nn = $entry; + if (-d "$d/$entry") { + $nn .= '/'; + } + $fx{$nn}{$d} = 1; + } + closedir $dh; + } + my $mm=scalar @dirlist; + my @out=(\@dirlist); + foreach my $f (sort keys %fx) { + unless (scalar keys %{$fx{$f}} == $mm) { + my @l; + foreach my $d (@dirlist) { + if (exists $fx{$f}{$d}) { + push @l,$f; + } else { + push @l,''; + } + } + push @out,\@l; + } + } + return \@out; +} + + +sub tabular($d) { + my @columnlength; + foreach my $row (@{$d}) { + foreach my $colno (0..$#{$row}) { + if (!defined($columnlength[$colno]) || + $columnlength[$colno] < length($row->[$colno])) { + $columnlength[$colno]=length($row->[$colno]); + } + } + } + my $format=join(' | ',map {"%-${_}s"} @columnlength); + my $result=''; + foreach my $row (@{$d}) { + $result .= sprintf($format,@{$row})."\n"; + } + return $result; +} + +print tabular(kdd("dir_a","dir_b","dir_c")); diff --git a/challenge-166/roger-bell-west/postscript/ch-1.ps b/challenge-166/roger-bell-west/postscript/ch-1.ps new file mode 100644 index 0000000000..3fed3b9fe5 --- /dev/null +++ b/challenge-166/roger-bell-west/postscript/ch-1.ps @@ -0,0 +1,263 @@ +%!PS + +/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 + +/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 + +/filter { % array proc(bool) -> array + 1 dict begin + /p exch def + [ exch + { + dup p not + { + pop + } if + } forall + ] + end +} bind def + +/reduce_init { % value array proc -> value + 2 dict begin + /p exch def + /a exch def + 0 1 a length 1 sub { + a exch get + p + } for + end +} bind def + +/strconcat % (a) (b) -> (ab) +{ exch dup length + 2 index length add string + dup dup 4 2 roll copy length + 4 -1 roll putinterval +} bind def + +/strjoin % [(a) (b) (c)] (j) -> (ajbjc) +{ + 3 dict begin + /j exch def + dup 0 get /out exch def + /first true def + { + first { + pop + /first false def + } { + out j strconcat + exch strconcat + /out exch def + } ifelse + } forall + out + end +} bind def + +/strsplit % (ajbjc) (j) -> [ (a) (b) (c) ] +{ + 1 dict begin + /sep exch def + [ exch + { + dup length 0 eq { + pop + exit + } { + sep search { + exch pop + dup length 0 eq { + pop + } { + exch + } ifelse + } { + () + } ifelse + } ifelse + } loop + ] + end +} bind def + +/cartesianproduct { % [ [ a b ] [ c d ] ] -> [ [ a c ] [ a d ] [ b c ] [ b d ] ] + 5 dict begin + /pat exch def + /c [ pat length { 0 } repeat ] def + /cm [ pat { length 1 sub } forall ] def + /ex false def + [ + { + ex { + exit + } if + [ + 0 1 c length 1 sub { + /i exch def + pat i get c i get get + } for + ] + /ss c length 1 sub def + { + c ss c ss get 1 add put + c ss get cm ss get gt { + ss 0 eq { + /ex true def + exit + } if + c ss 0 put + /ss ss 1 sub def + } { + exit + } ifelse + } loop + } loop + end + ] +} bind def + +/hexwords { + 7 dict begin + /sb exch def + /hi exch def + /lo exch def + /abcdef (abcdef) def + /oilst (oilst) def + [ + (dictionary.txt) (r) file dup bytesavailable string readstring pop + (\n) strsplit { + dup length dup lo ge exch hi le and { + /valid true def + /sbc 0 def + dup { + (.) dup 0 3 index put exch pop + dup oilst exch search { + pop pop pop pop + /sbc sbc 1 add def + sbc sb gt { + /valid false def + } if + } { + pop + abcdef exch search { + pop pop pop + } { + pop + /valid false def + } ifelse + } ifelse + valid not { + exit + } if + } forall + valid not { + pop + } if + } { + pop + } ifelse + } forall + ] + end +} bind def + +/combiwords { + 7 dict begin + /l exch def + /wh 0 dict def + { + dup length /lx exch def + wh lx known not { + wh lx 0 array put + } if + wh lx get exch apush.right wh exch lx exch put + } forall + /tmap [ 0 array ] def + /omap 0 array def + { + tmap length 0 eq { + exit + } if + tmap apop.right /c exch def /tmap exch def + /s 0 c { add } reduce_init def + 1 1 l s sub { + /j exch def + wh j known { + /tmap tmap c j apush.right apush.right def + } if + } for + wh l s sub known { + /omap omap c l s sub apush.right apush.right def + } if + } loop + [ + omap { + [ exch + { wh exch get } forall + ] + cartesianproduct + { + () strjoin + } forall + } forall + ] + end +} bind def + +(hexwords) test.start +2 8 8 hexwords length 1463 eq test +8 8 8 hexwords length 164 eq test +2 8 0 hexwords length 45 eq test +2 8 1 hexwords length 244 eq test +test.end + +(combiwords) test.start +4 4 0 hexwords 8 combiwords length 144 eq test +3 5 0 hexwords 8 combiwords length 274 eq test +test.end diff --git a/challenge-166/roger-bell-west/postscript/ch-2.ps b/challenge-166/roger-bell-west/postscript/ch-2.ps new file mode 100644 index 0000000000..46dac29cb2 --- /dev/null +++ b/challenge-166/roger-bell-west/postscript/ch-2.ps @@ -0,0 +1,206 @@ +%! PS + +/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 + +/strconcat % (a) (b) -> (ab) +{ exch dup length + 2 index length add string + dup dup 4 2 roll copy length + 4 -1 roll putinterval +} bind def + +/strjoin % [(a) (b) (c)] (j) -> (ajbjc) +{ + 3 dict begin + /j exch def + dup 0 get /out exch def + /first true def + { + first { + pop + /first false def + } { + out j strconcat + exch strconcat + /out exch def + } ifelse + } forall + out + end +} bind def + +/toset { % array -> dict of (array, true) + << exch + { + true + } forall + >> +} bind def + +/keys { % dict -> array of dict keys + [ exch + { + pop + } forall + ] +} bind def + +/map { % array proc -> array + 2 dict begin + /p exch def + [ exch + { + p + } forall + ] +} bind def + +/kdd { + 2 dict begin + /dirlist exch quicksort def + /fx dirlist length dict def + dirlist { + /d exch def + [ + d (/*/) strconcat + { + dup length d length 1 add dup 3 1 roll sub 2 -1 roll exch getinterval + dup length string cvs + } 50 string filenameforall + ] { + /f exch def + fx f known not { + fx f dirlist length dict put + } if + fx f get d true put + } forall + } forall + /mm dirlist length def + [ + dirlist + fx keys { dup length string cvs } map quicksort { + /f exch def + fx f get length mm ne { + [ + dirlist { + fx f get exch + known { + f + } { + () + } ifelse + } forall + ] + } if + } forall + ] + end +} bind def + +/spaces { + 2 dict begin + /space ( ) 0 get def + dup /st exch string def + 0 exch 1 exch 1 sub { + st exch space put + } for + st + end +} bind def + +/tabular { + 1 dict begin + /d exch def + /columnlength [ + d 0 get { + pop 0 + } forall + ] def + d { + /row exch def + 0 1 row length 1 sub { + /i exch def + columnlength i columnlength i get row i get length max put + } for + } forall + d { + /row exch def + 0 1 row length 1 sub { + /i exch def + i 0 gt { + ( | ) print + } if + columnlength i get spaces dup 0 row i get putinterval print + } for + (\n) print + } forall + end +} bind def + +[ (dir_a) (dir_b) (dir_c) ] kdd tabular diff --git a/challenge-166/roger-bell-west/python/ch-1.py b/challenge-166/roger-bell-west/python/ch-1.py new file mode 100755 index 0000000000..59f29c8748 --- /dev/null +++ b/challenge-166/roger-bell-west/python/ch-1.py @@ -0,0 +1,87 @@ +#! /usr/bin/python3 + +import unittest + +from collections import defaultdict +from functools import reduce +from itertools import product +import operator + +def hexwords(lo,hi,sb): + out = [] + fh = open('dictionary.txt','r') + for ll in fh: + line = ll.rstrip() + if len(line) >= lo and len(line) <= hi: + valid = True + sbc = 0 + for c in line: + if c == 'o' or c == 'i' or c == 'l' or c == 's' or c == 't': + sbc += 1 + if sbc > sb: + valid = False + elif c < 'a' or c > 'f': + valid = False + if not valid: + break + if valid: + out.append(line) + fh.close() + return out + +def combiwords(wl,l): + wh = defaultdict(list) + for w in wl: + wh[len(w)].append(w) + tmap = [[]] + omap = [] + while len(tmap) > 0: + c = tmap.pop() + s = reduce(operator.add,c,0) + for j in range(1,l-s): + if j in wh: + cc = c.copy() + cc.append(j) + tmap.append(cc) + if l-s in wh: + c.append(l-s) + omap.append(c) + out = [] + for pat in omap: + for wx in product(*[wh[x] for x in pat]): + out.append("".join(wx)) + return out + +class TestHexwords(unittest.TestCase): + + def test_ex1(self): + self.assertEqual(len(hexwords(2,8,8)), + 1463, + 'example 1') + + def test_ex2(self): + self.assertEqual(len(hexwords(8,8,8)), + 164, + 'example 2') + + def test_ex3(self): + self.assertEqual(len(hexwords(2,8,0)), + 45, + 'example 3') + + def test_ex4(self): + self.assertEqual(len(hexwords(2,8,1)), + 244, + 'example 4') + + def test_ex5(self): + self.assertEqual(len(combiwords(hexwords(4,4,0),8)), + 144, + 'example 5') + + def test_ex6(self): + self.assertEqual(len(combiwords(hexwords(3,5,0),8)), + 274, + 'example 6') + +unittest.main() diff --git a/challenge-166/roger-bell-west/python/ch-2.py b/challenge-166/roger-bell-west/python/ch-2.py new file mode 100755 index 0000000000..0812574aa2 --- /dev/null +++ b/challenge-166/roger-bell-west/python/ch-2.py @@ -0,0 +1,39 @@ +#! /usr/bin/python3 + +from collections import defaultdict +import os + +def kdd(dirlist0): + dirlist = sorted(dirlist0) + fx = defaultdict(set) + for d in dirlist: + for entry in os.scandir(d): + nn = entry.name + if entry.is_dir(): + nn += '/' + fx[nn].add(d) + mm = len(dirlist) + out = [dirlist] + for f in sorted(fx.keys()): + if not len(fx[f]) == mm: + l = [] + for d in dirlist: + if d in fx[f]: + l.append(f) + else: + l.append('') + out.append(l) + return out + +def tabular(d): + columnlength = [] + for row in d: + for i,col in enumerate(row): + while len(columnlength) <= i: + columnlength.append(0) + columnlength[i] = max([columnlength[i],len(col)]) + fs = " | ".join("{:<" + str(x) + "}" for x in columnlength) + for row in d: + print(fs.format(*row)) + +tabular(kdd(["dir_a","dir_b","dir_c"])) diff --git a/challenge-166/roger-bell-west/raku/ch-1.p6 b/challenge-166/roger-bell-west/raku/ch-1.p6 new file mode 100755 index 0000000000..c3c386a7b2 --- /dev/null +++ b/challenge-166/roger-bell-west/raku/ch-1.p6 @@ -0,0 +1,79 @@ +#! /usr/bin/perl6 + +use Test; + +plan 6; + +is(hexwords(2,8,8).elems(),1463,'example 1'); + +is(hexwords(8,8,8).elems(),164,'example 2'); + +is(hexwords(2,8,0).elems(),45,'example 3'); + +is(hexwords(2,8,1).elems(),244,'example 4'); + +is(combiwords(hexwords(4,4,0),8).elems(),144,'example 5'); + +is(combiwords(hexwords(3,5,0),8).elems(),274,'example 6'); + +sub hexwords($lo,$hi,$sb) { + my @out; + for 'dictionary.txt'.IO.lines -> $line { + if ($line.chars() >= $lo && $line.chars() <= $hi) { + my $valid = True; + my $sbc = 0; + for $line.comb() -> $c { + if ($c ~~ /<[oilst]>/) { + $sbc++; + if ($sbc > $sb) { + $valid = False; + } + } elsif ($c lt 'a' || $c gt 'f') { + $valid = False; + } + unless ($valid) { + last; + } + } + if ($valid) { + @out.push($line); + } + } + } + return @out; +} + +sub combiwords(@wl,$l) { + my %wh; + for @wl -> $w { + %wh{$w.chars()}.push($w); + } + my @tmap=[[],]; + my @omap; + while (@tmap.elems() > 0) { + my @c=@tmap.pop().flat; + my $s=@c.sum(); + for (1..$l-$s-1) -> $j { + if (%wh{$j}:exists) { + my @cc = @c».List.flat; + @cc.push($j); + @tmap.push(@cc); + } + } + if (%wh{$l-$s}:exists) { + @c.push($l-$s); + @omap.push(@c); + } + } + my @out; + for @omap -> @pat { + my @c = %wh{@pat[0]}.List; + for (1..@pat.elems()-1) -> $i { + @c = @c X %wh{@pat[$i]}.List; + } + for @c -> @ww { + @out.push(@ww.join('')); + } + } + return @out; +} diff --git a/challenge-166/roger-bell-west/raku/ch-2.p6 b/challenge-166/roger-bell-west/raku/ch-2.p6 new file mode 100755 index 0000000000..3d92aa1012 --- /dev/null +++ b/challenge-166/roger-bell-west/raku/ch-2.p6 @@ -0,0 +1,51 @@ +#! /usr/bin/perl6 + +sub kdd(@dirlist0) { + my @dirlist = @dirlist0.sort(); + my %fx; + for @dirlist -> $d { + for dir($d) -> $entry { + my $nn = $entry; + $nn ~~ s/.*\///; + if ($entry.d()) { + $nn ~= '/'; + } + %fx{$nn} ||= SetHash.new(); + %fx{$nn}{$d}++; + } + } + my $mm=@dirlist.elems(); + my @out=[@dirlist,]; + for %fx.keys().sort() -> $f { + unless (%fx{$f}.elems() == $mm) { + my @l; + for @dirlist -> $d { + if (%fx{$f}{$d}:exists) { + @l.push($f); + } else { + @l.push(''); + } + } + @out.push(@l); + } + } + return @out; +} + +sub tabular(@d) { + my @columnlength; + for @d -> @row { + for (0..@row.elems-1) -> $i { + while (@columnlength.elems() <= $i) { + @columnlength.push(0); + } + @columnlength[$i]=max(@columnlength[$i],@row[$i].chars()); + } + } + my $format=@columnlength.map({'%-' ~ $_ ~ 's'}).join(' | ') ~ "\n"; + for @d -> @row { + $format.printf(@row); + } +} + +tabular(kdd(["dir_a","dir_b","dir_c"])); diff --git a/challenge-166/roger-bell-west/ruby/ch-1.rb b/challenge-166/roger-bell-west/ruby/ch-1.rb new file mode 100755 index 0000000000..bb1f81d304 --- /dev/null +++ b/challenge-166/roger-bell-west/ruby/ch-1.rb @@ -0,0 +1,103 @@ +#! /usr/bin/ruby + +require 'test/unit' + +def hexwords(lo,hi,sb) + out = [] + File.open('dictionary.txt','r') do |fh| + fh.each_line("\n") do |line| + line = line.chomp + if line.length >= lo && line.length <= hi then + valid = true + sbc = 0 + line.chars do |c| + if c == 'o' || c == 'i' || c == 'l' || c == 's' || c == 't' then + sbc += 1 + if sbc > sb then + valid = false + end + elsif c < 'a' || c > 'f' then + valid = false + end + if !valid then + break + end + end + if valid then + out.push(line) + end + end + end + end + return out +end + +def combiwords(wl,l) + wh = Hash.new + wl.each do |w| + lx = w.length + if !wh.has_key?(lx) then + wh[lx] = [] + end + wh[lx].push(w) + end + tmap = [ [] ] + omap = [] + while tmap.length > 0 do + c = tmap.pop + s = c.sum + 1.upto(l-s-1) do |j| + if wh.has_key?(j) then + cc = c[0..-1] + cc.push(j) + tmap.push(cc) + end + end + if wh.has_key?(l-s) then + c.push(l-s) + omap.push(c) + end + end + out = [] + omap.each do |pat| + wh[pat[0]].product(pat[1..-1].collect{|i| wh[i]}.flatten).each do |w| + out.push(w.join("")) + end + end + return out +end + +class TestHexwords < Test::Unit::TestCase + + def test_ex1 + assert_equal(1463, + hexwords(2,8,8).length) + end + + def test_ex2 + assert_equal(164, + hexwords(8,8,8).length) + end + + def test_ex3 + assert_equal(45, + hexwords(2,8,0).length) + end + + def test_ex4 + assert_equal(244, + hexwords(2,8,1).length) + end + + def test_ex5 + assert_equal(144, + combiwords(hexwords(4,4,0),8).length) + end + + def test_ex6 + assert_equal(274, + combiwords(hexwords(3,5,0),8).length) + end + +end + diff --git a/challenge-166/roger-bell-west/ruby/ch-2.rb b/challenge-166/roger-bell-west/ruby/ch-2.rb new file mode 100755 index 0000000000..90c54049a9 --- /dev/null +++ b/challenge-166/roger-bell-west/ruby/ch-2.rb @@ -0,0 +1,54 @@ +#! /usr/bin/ruby + +require 'set' + +def kdd(dirlist0) + dirlist = dirlist0.sort + fx = Hash.new + dirlist.each do |d| + Dir.new(d).each do |entry| + nn = entry + if File.directory?(d + "/" + entry) then + nn += '/' + end + if !fx.has_key?(nn) then + fx[nn]=Set.new + end + fx[nn].add(d) + end + end + mm = dirlist.length + out = [dirlist] + fx.keys.sort.each do |f| + if !(fx[f].length == mm) then + l = [] + dirlist.each do |d| + if fx[f].include?(d) then + l.push(f) + else + l.push("") + end + end + out.push(l) + end + end + return out +end + +def tabular(d) + columnlength = [] + d.each do |row| + row.each_with_index do |col,i| + while columnlength.length <= i do + columnlength.push(0) + end + columnlength[i] = [columnlength[i],col.length].max + end + end + fs = columnlength.collect{|i| "%-" + i.to_s + "s"}.join(" | ") + d.each do |row| + puts(fs % row) + end +end + +tabular(kdd(["dir_a","dir_b","dir_c"])) diff --git a/challenge-166/roger-bell-west/rust/ch-1.rs b/challenge-166/roger-bell-west/rust/ch-1.rs new file mode 100644 index 0000000000..16366fc58b --- /dev/null +++ b/challenge-166/roger-bell-west/rust/ch-1.rs @@ -0,0 +1,97 @@ +use itertools::Itertools; +use std::collections::HashMap; +use std::fs::File; +use std::io::{prelude::*, BufReader}; + +#[test] +fn test_ex1() { + assert_eq!(hexwords(2, 8, 8).len(), 1463); +} + +#[test] +fn test_ex2() { + assert_eq!(hexwords(8, 8, 8).len(), 164); +} + +#[test] +fn test_ex3() { + assert_eq!(hexwords(2, 8, 0).len(), 45); +} + +#[test] +fn test_ex4() { + assert_eq!(hexwords(2, 8, 1).len(), 244); +} + +#[test] +fn test_ex5() { + assert_eq!(combiwords(hexwords(4, 4, 0), 8).len(), 144); +} + +#[test] +fn test_ex6() { + assert_eq!(combiwords(hexwords(3, 5, 0), 8).len(), 274); +} + +fn hexwords(lo: usize, hi: usize, sb: usize) -> Vec { + let mut out: Vec = Vec::new(); + let file = File::open("dictionary.txt").unwrap(); + let reader = BufReader::new(file); + for lx in reader.lines() { + let line = lx.unwrap(); + if line.len() >= lo && line.len() <= hi { + let mut valid = true; + let mut sbc = 0; + for c in line.chars() { + if c == 'o' || c == 'i' || c == 'l' || c == 's' || c == 't' { + sbc += 1; + if sbc > sb { + valid = false; + } + } else if c < 'a' || c > 'f' { + valid = false; + } + if !valid { + break; + } + } + if valid { + out.push(line); + } + } + } + out +} + +fn combiwords(wl: Vec, l: usize) -> Vec { + let mut wh: HashMap> = HashMap::new(); + for w in wl { + let en = wh.entry(w.len()).or_insert(Vec::new()); + (*en).push(w); + } + let mut tmap: Vec> = vec![Vec::new()]; + let mut omap: Vec> = Vec::new(); + while tmap.len() > 0 { + let mut c = tmap.pop().unwrap(); + let s = &c.iter().sum::(); + let ls = l - s; + for j in 1..ls { + if wh.contains_key(&j) { + let mut cc = c.clone(); + cc.push(j); + tmap.push(cc); + } + } + if wh.contains_key(&ls) { + c.push(ls); + omap.push(c); + } + } + let mut out: Vec = Vec::new(); + for pat in omap { + for ss in pat.iter().map(|i| &wh[i]).multi_cartesian_product() { + out.push(ss.iter().join("")); + } + } + out +} diff --git a/challenge-166/roger-bell-west/rust/ch-2.rs b/challenge-166/roger-bell-west/rust/ch-2.rs new file mode 100755 index 0000000000..7aec3eeb5c --- /dev/null +++ b/challenge-166/roger-bell-west/rust/ch-2.rs @@ -0,0 +1,75 @@ +#! /bin/sh +//usr/bin/env rustc $0 -o ${0}x && ./${0}x --nocapture; rm -f ${0}x ; exit + +use std::cmp::max; +use std::collections::{HashMap, HashSet}; +use std::fs; + +fn kdd(dirlist0: Vec) -> Vec> { + let mut dirlist = dirlist0; + dirlist.sort(); + let mut fx: HashMap> = HashMap::new(); + for d in &dirlist { + for e in fs::read_dir(&d).unwrap() { + let entry = e.unwrap(); + let mut nn = entry.file_name().to_string_lossy().to_string(); + if entry.file_type().unwrap().is_dir() { + nn.push('/'); + } + let en = fx.entry(nn).or_insert(HashSet::new()); + (*en).insert(d.clone()); + } + } + let mm = (&dirlist).len(); + let mut out: Vec> = vec![dirlist.clone()]; + let mut ff = fx.keys().map(|i| format!("{}", i)).collect::>(); + ff.sort(); + for f in ff { + if fx.get(&f).unwrap().len() != mm { + let mut l: Vec = Vec::new(); + for d in &dirlist { + if fx.get(&f).unwrap().contains(d) { + l.push((*f).to_string()); + } else { + l.push("".to_string()); + } + } + out.push(l); + } + } + out +} + +fn strpad(x: &String, width: usize) -> String { + let mut y = x.clone(); + while y.len() < width { + y.push(' '); + } + return y; +} + +fn tabular(d: Vec>) { + let mut columnlength = vec![0; d[0].len()]; + for row in &d { + for (i, col) in row.iter().enumerate() { + columnlength[i] = max(columnlength[i], col.len()); + } + } + for row in &d { + for (i, col) in row.iter().enumerate() { + if i > 0 { + print!(" | ") + } + print!("{}", strpad(col, columnlength[i])); + } + println!(""); + } +} + +fn main() { + tabular(kdd(vec![ + "dir_a".to_string(), + "dir_b".to_string(), + "dir_c".to_string(), + ])); +} -- cgit