From 1c6cd189ee4f8416961ec458aebe5449accc7aaf Mon Sep 17 00:00:00 2001 From: Roger Bell_West Date: Tue, 18 Jun 2024 10:27:04 +0100 Subject: RogerBW solutions for challenge no. 274 --- challenge-274/roger-bell-west/crystal/ch-1.cr | 32 ++++ challenge-274/roger-bell-west/crystal/ch-2.cr | 57 ++++++ challenge-274/roger-bell-west/javascript/ch-1.js | 40 ++++ challenge-274/roger-bell-west/javascript/ch-2.js | 93 ++++++++++ challenge-274/roger-bell-west/kotlin/ch-1.kt | 48 +++++ challenge-274/roger-bell-west/kotlin/ch-2.kt | 61 +++++++ challenge-274/roger-bell-west/lua/ch-1.lua | 86 +++++++++ challenge-274/roger-bell-west/lua/ch-2.lua | 104 +++++++++++ challenge-274/roger-bell-west/perl/ch-1.pl | 28 +++ challenge-274/roger-bell-west/perl/ch-2.pl | 57 ++++++ challenge-274/roger-bell-west/postscript/ch-1.ps | 158 ++++++++++++++++ challenge-274/roger-bell-west/postscript/ch-2.ps | 221 +++++++++++++++++++++++ challenge-274/roger-bell-west/python/ch-1.py | 33 ++++ challenge-274/roger-bell-west/python/ch-2.py | 47 +++++ challenge-274/roger-bell-west/raku/ch-1.p6 | 26 +++ challenge-274/roger-bell-west/raku/ch-2.p6 | 51 ++++++ challenge-274/roger-bell-west/ruby/ch-1.rb | 37 ++++ challenge-274/roger-bell-west/ruby/ch-2.rb | 63 +++++++ challenge-274/roger-bell-west/rust/ch-1.rs | 47 +++++ challenge-274/roger-bell-west/rust/ch-2.rs | 68 +++++++ challenge-274/roger-bell-west/scala/ch-1.scala | 49 +++++ challenge-274/roger-bell-west/scala/ch-2.scala | 65 +++++++ challenge-274/roger-bell-west/tests.json | 35 ++++ 23 files changed, 1506 insertions(+) create mode 100755 challenge-274/roger-bell-west/crystal/ch-1.cr create mode 100755 challenge-274/roger-bell-west/crystal/ch-2.cr create mode 100755 challenge-274/roger-bell-west/javascript/ch-1.js create mode 100755 challenge-274/roger-bell-west/javascript/ch-2.js create mode 100644 challenge-274/roger-bell-west/kotlin/ch-1.kt create mode 100644 challenge-274/roger-bell-west/kotlin/ch-2.kt create mode 100755 challenge-274/roger-bell-west/lua/ch-1.lua create mode 100755 challenge-274/roger-bell-west/lua/ch-2.lua create mode 100755 challenge-274/roger-bell-west/perl/ch-1.pl create mode 100755 challenge-274/roger-bell-west/perl/ch-2.pl create mode 100644 challenge-274/roger-bell-west/postscript/ch-1.ps create mode 100644 challenge-274/roger-bell-west/postscript/ch-2.ps create mode 100755 challenge-274/roger-bell-west/python/ch-1.py create mode 100755 challenge-274/roger-bell-west/python/ch-2.py create mode 100755 challenge-274/roger-bell-west/raku/ch-1.p6 create mode 100755 challenge-274/roger-bell-west/raku/ch-2.p6 create mode 100755 challenge-274/roger-bell-west/ruby/ch-1.rb create mode 100755 challenge-274/roger-bell-west/ruby/ch-2.rb create mode 100755 challenge-274/roger-bell-west/rust/ch-1.rs create mode 100755 challenge-274/roger-bell-west/rust/ch-2.rs create mode 100644 challenge-274/roger-bell-west/scala/ch-1.scala create mode 100644 challenge-274/roger-bell-west/scala/ch-2.scala create mode 100644 challenge-274/roger-bell-west/tests.json diff --git a/challenge-274/roger-bell-west/crystal/ch-1.cr b/challenge-274/roger-bell-west/crystal/ch-1.cr new file mode 100755 index 0000000000..ae0cc9b8e5 --- /dev/null +++ b/challenge-274/roger-bell-west/crystal/ch-1.cr @@ -0,0 +1,32 @@ +#! /usr/bin/crystal + +def goatlatin(a) + out = [] of String + a.split(" ").each_with_index do |word, ix| + c = word.split("") + if c[0] !~ /[aeiou]/i + co = c.shift; + c.push(co) + end + nw = c.join("") + nw += "ma" + 0.upto(ix) do + nw += "a" + end + out.push(nw) + end + out.join(" ") +end + +require "spec" +describe "goatlatin" do + it "test_ex1" do + goatlatin("I love Perl").should eq "Imaa ovelmaaa erlPmaaaa" + end + it "test_ex2" do + goatlatin("Perl and Raku are friends").should eq "erlPmaa andmaaa akuRmaaaa aremaaaaa riendsfmaaaaaa" + end + it "test_ex3" do + goatlatin("The Weekly Challenge").should eq "heTmaa eeklyWmaaa hallengeCmaaaa" + end +end diff --git a/challenge-274/roger-bell-west/crystal/ch-2.cr b/challenge-274/roger-bell-west/crystal/ch-2.cr new file mode 100755 index 0000000000..36f4fa8789 --- /dev/null +++ b/challenge-274/roger-bell-west/crystal/ch-2.cr @@ -0,0 +1,57 @@ +#! /usr/bin/crystal + +def busroute(a) + route = [] of Hash(Int32, Int32) + a.each do |rt| + ri = Hash(Int32, Int32).new + interval, offset, duration = rt + start = offset + while true + if start > 60 + offset + break + end + ri[start] = start + duration + start += interval + end + route.push(ri) + end + out = [] of Int32 + 0.upto(59) do |t| + best = Set(Int32).new + at = -1 + nxt = Set(Int32).new + ndt = -1 + route.each_with_index do |r, i| + nb = r.keys.select { |n| n >= t }.min + nt = r[nb] + if at == -1 || nt < at + best.clear + at = nt + end + if nt <= at + best.add(i) + end + if ndt == -1 || nb < ndt + nxt.clear + ndt = nb + end + if nb <= ndt + nxt.add(i) + end + end + if (best & nxt) .size == 0 + out.push(t) + end + end + out +end + +require "spec" +describe "busroute" do + it "test_ex1" do + busroute([[12, 11, 41], [15, 5, 35]]).should eq [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47] + end + it "test_ex2" do + busroute([[12, 3, 41], [15, 9, 35], [30, 5, 25]]).should eq [0, 1, 2, 3, 25, 26, 27, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59] + end +end diff --git a/challenge-274/roger-bell-west/javascript/ch-1.js b/challenge-274/roger-bell-west/javascript/ch-1.js new file mode 100755 index 0000000000..b300b4d51f --- /dev/null +++ b/challenge-274/roger-bell-west/javascript/ch-1.js @@ -0,0 +1,40 @@ +#! /usr/bin/node + +"use strict" + +function goatlatin(a) { + let out = []; + a.split(" ").forEach((word, ix) => { + let c = word.split(""); + if (!c[0].match(/[aeiou]/i)) { + let co = c.shift(); + c.push(co); + } + let nw = c.join(""); + nw += "ma"; + for (let i = 0; i <= ix; i++) { + nw += "a"; + } + out.push(nw) + }); + return out.join(" "); +} + +if (goatlatin('I love Perl') == 'Imaa ovelmaaa erlPmaaaa') { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); +if (goatlatin('Perl and Raku are friends') == 'erlPmaa andmaaa akuRmaaaa aremaaaaa riendsfmaaaaaa') { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); +if (goatlatin('The Weekly Challenge') == 'heTmaa eeklyWmaaa hallengeCmaaaa') { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write("\n"); diff --git a/challenge-274/roger-bell-west/javascript/ch-2.js b/challenge-274/roger-bell-west/javascript/ch-2.js new file mode 100755 index 0000000000..a067c154bb --- /dev/null +++ b/challenge-274/roger-bell-west/javascript/ch-2.js @@ -0,0 +1,93 @@ +#! /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 busroute(a) { + let route = []; + for (let rt of a) { + let ri = new Map; + const interval = rt[0]; + const offset = rt[1]; + const duration = rt[2]; + let start = offset; + while (true) { + if (start > 60 + offset) { + break; + } + ri.set(start, start + duration); + start += interval; + } + route.push(ri); + } + let out = []; + for (let t = 0; t < 60; t++) { + let best = new Set; + let at = -1; + let nxt = new Set; + let ndt = -1; + route.forEach((r, i) => { + const nb = Math.min(...([...r.keys()].filter(n => n >= t))); + const nt = r.get(nb); + if (at == -1 || nt < at) { + best = new Set; + at = nt; + } + if (nt <= at) { + best.add(i); + } + if (ndt == -1 || nb < ndt) { + nxt = new Set; + ndt = nb; + } + if (nb <= ndt) { + nxt.add(i); + } + }); + const intersect = new Set([...best].filter(i => nxt.has(i))); + if (intersect.size == 0) { + out.push(t); + } + } + return out; +} + + +if (deepEqual(busroute([[12, 11, 41], [15, 5, 35]]), [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47])) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); +if (deepEqual(busroute([[12, 3, 41], [15, 9, 35], [30, 5, 25]]), [0, 1, 2, 3, 25, 26, 27, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59])) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write("\n"); diff --git a/challenge-274/roger-bell-west/kotlin/ch-1.kt b/challenge-274/roger-bell-west/kotlin/ch-1.kt new file mode 100644 index 0000000000..5e2e3bbb4c --- /dev/null +++ b/challenge-274/roger-bell-west/kotlin/ch-1.kt @@ -0,0 +1,48 @@ +fun is_vowel(c: Char): Boolean { + return when (c.lowercaseChar()) { + 'a', 'e', 'i', 'o', 'u' -> true + else -> false + } +} + +fun goatlatin(a: String): String { + var out = ArrayList() + a.split(" ").forEachIndexed {i, word -> + var c = word.toList() + var nw = StringBuilder(word); + if (!is_vowel(c[0])) { + var co = ArrayList(c.drop(1)) + co.add(c[0]) + nw = StringBuilder(co.joinToString("")) + } + nw.append("ma") + for (ix in 0..i) { + nw.append("a") + } + out.add(nw.toString()) + } + return out.joinToString(" ") +} + +fun main() { + + if (goatlatin("I love Perl") == "Imaa ovelmaaa erlPmaaaa") { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (goatlatin("Perl and Raku are friends") == "erlPmaa andmaaa akuRmaaaa aremaaaaa riendsfmaaaaaa") { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (goatlatin("The Weekly Challenge") == "heTmaa eeklyWmaaa hallengeCmaaaa") { + print("Pass") + } else { + print("Fail") + } + println("") + +} diff --git a/challenge-274/roger-bell-west/kotlin/ch-2.kt b/challenge-274/roger-bell-west/kotlin/ch-2.kt new file mode 100644 index 0000000000..a09d3869a4 --- /dev/null +++ b/challenge-274/roger-bell-west/kotlin/ch-2.kt @@ -0,0 +1,61 @@ +fun busroute(a: List>): List { + var route = ArrayList>() + for (rt in a) { + var ri = mutableMapOf() + val interval = rt[0] + val offset = rt[1] + val duration = rt[2] + var start = offset + while (start <= 60 + offset) { + ri.put(start, start + duration) + start += interval + } + route.add(ri) + } + var out = ArrayList() + for (t in 0 .. 59) { + var best = mutableSetOf() + var at = -1 + var nxt = mutableSetOf() + var ndt = -1 + route.forEachIndexed {i, r -> + val nb = r.keys.filter{it >= t}.minOrNull()!! + val nt = r.getValue(nb) + if (at == -1 || nt < at) { + best = mutableSetOf() + at = nt + } + if (nt <= at) { + best.add(i) + } + if (ndt == -1 || nb < ndt) { + nxt = mutableSetOf() + ndt = nb + } + if (nb <= ndt) { + nxt.add(i) + } + } + if (best.intersect(nxt).isEmpty()) { + out.add(t) + } + } + return out.toList() +} + +fun main() { + + if (busroute(listOf(listOf(12, 11, 41), listOf(15, 5, 35))) == listOf(36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47)) { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (busroute(listOf(listOf(12, 3, 41), listOf(15, 9, 35), listOf(30, 5, 25))) == listOf(0, 1, 2, 3, 25, 26, 27, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59)) { + print("Pass") + } else { + print("Fail") + } + println("") + +} diff --git a/challenge-274/roger-bell-west/lua/ch-1.lua b/challenge-274/roger-bell-west/lua/ch-1.lua new file mode 100755 index 0000000000..1127f03cb4 --- /dev/null +++ b/challenge-274/roger-bell-west/lua/ch-1.lua @@ -0,0 +1,86 @@ +#! /usr/bin/lua + +-- bart at https://stackoverflow.com/questions/1426954/split-string-in-lua +function splits(inputstr, sep) + sep=sep or '%s' + local t={} + for field,s in string.gmatch(inputstr, "([^"..sep.."]*)("..sep.."?)") do + table.insert(t,field) + if s=="" then + return t + end + end +end + +function split(t) + local cl = {} + string.gsub(t, + "(.)", + function(c) + table.insert(cl, c) + end + ) + return cl +end + +function join(t) + local out="" + for i, v in ipairs(t) do + out = out .. v + end + return out +end + +function joins(t,pad) + local out="" + local later = false + for k,v in pairs(t) do + if later then + out = out .. pad + end + out = out .. v + later = true + end + return out +end + +function goatlatin(a) + local out = {} + for ix, word in ipairs(splits(a, " ")) do + local nw = word + local c = split(word) + if string.match(c[1], "[^aeiouAEIOU]") then + table.insert(c, c[1]) + table.remove(c, 1) + nw = join(c) + end + nw = nw .. "ma" + for i = 1, ix do + nw = nw .. "a" + end + table.insert(out, nw) + end + return joins(out, " ") +end + +if goatlatin("I love Perl") == "Imaa ovelmaaa erlPmaaaa" then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if goatlatin("Perl and Raku are friends") == "erlPmaa andmaaa akuRmaaaa aremaaaaa riendsfmaaaaaa" then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if goatlatin("The Weekly Challenge") == "heTmaa eeklyWmaaa hallengeCmaaaa" then + io.write("Pass") +else + io.write("FAIL") +end +print("") + diff --git a/challenge-274/roger-bell-west/lua/ch-2.lua b/challenge-274/roger-bell-west/lua/ch-2.lua new file mode 100755 index 0000000000..2f50581f13 --- /dev/null +++ b/challenge-274/roger-bell-west/lua/ch-2.lua @@ -0,0 +1,104 @@ +#! /usr/bin/lua + +-- by Michael Anderson at +-- https://stackoverflow.com/questions/8722620/comparing-two-index-tables-by-index-value-in-lua +-- 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 busroute(a) + local routes = {} + for _, rt in ipairs(a) do + local ri = {} + local interval = rt[1] + local offset = rt[2] + local duration = rt[3] + local start = offset + while start <= 60 + offset do + ri[start] = start + duration + start = start + interval + end + table.insert(routes, rt) + end + local out = {} + for t = 0, 59 do + local best = {} + local at = -1 + local nxt = {} + local ndt = -1 + for i, r in ipairs(routes) do + local nb = 999 + local nt = 0 + for n, l in ipairs(r) do + if n >= t then + if l < nb then + nb = n + nt = l + end + end + end + if at == -1 or nt < at then + best = {} + at = nt + end + if nt <= at then + best[i] = true + end + if ndt == -1 or nb < ndt then + nxt = {} + ndt = nb + end + if nb <= ndt then + nxt[i] = true + end + end + local intersect = {} + for k, v in pairs(best) do + if nxt[k] ~= nil then + table.insert(intersect, k) + end + end + if #intersect == 0 then + table.insert(out, t) + end + end + return out +end + +if recursive_compare(busroute({{12, 11, 41}, {15, 5, 35}}), {36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}) then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if recursive_compare(busroute({{12, 3, 41}, {15, 9, 35}, {30, 5, 25}}), {0, 1, 2, 3, 25, 26, 27, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59}) then + io.write("Pass") +else + io.write("FAIL") +end +print("") + diff --git a/challenge-274/roger-bell-west/perl/ch-1.pl b/challenge-274/roger-bell-west/perl/ch-1.pl new file mode 100755 index 0000000000..6cb6190b8c --- /dev/null +++ b/challenge-274/roger-bell-west/perl/ch-1.pl @@ -0,0 +1,28 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use experimental 'signatures'; + +use Test::More tests => 3; + +is(goatlatin('I love Perl'), 'Imaa ovelmaaa erlPmaaaa', 'example 1'); +is(goatlatin('Perl and Raku are friends'), 'erlPmaa andmaaa akuRmaaaa aremaaaaa riendsfmaaaaaa', 'example 2'); +is(goatlatin('The Weekly Challenge'), 'heTmaa eeklyWmaaa hallengeCmaaaa', 'example 3'); + +sub goatlatin($a) { + my @out; + my @w = split ' ', $a; + while (my ($ix, $word) = each @w) { + my @c = split '',$word; + my $nw = $word; + if ($c[0] !~ /[aeiou]/i) { + push @c,shift @c; + $nw = join('', @c); + } + $nw .= 'ma'; + $nw .= 'a' x ($ix + 1); + push @out, $nw; + } + return join(' ', @out); +} diff --git a/challenge-274/roger-bell-west/perl/ch-2.pl b/challenge-274/roger-bell-west/perl/ch-2.pl new file mode 100755 index 0000000000..5a3ee1c7ae --- /dev/null +++ b/challenge-274/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 => 2; + +is_deeply(busroute([[12, 11, 41], [15, 5, 35]]), [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47], 'example 1'); +is_deeply(busroute([[12, 3, 41], [15, 9, 35], [30, 5, 25]]), [0, 1, 2, 3, 25, 26, 27, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59], 'example 2'); + +use List::Util qw(min); + +sub busroute($a) { + my @routes; + foreach my $rt (@{$a}) { + my %ri; + my ($interval, $offset, $duration) = @{$rt}; + my $start = $offset; + while ($start <= 60 + $offset) { + $ri{$start} = $start + $duration; + $start += $interval; + } + push @routes, \%ri; + } + my @out; + foreach my $t (0 .. 59) { + my %best; + my $at = -1; + my %nxt; + my $ndt = -1; + values @routes; + while (my ($i, $r) = each @routes) { + my $nb = min grep {$_ >= $t} keys(%{$r}); + my $nt = $r->{$nb}; + if ($at == -1 || $nt < $at) { + %best = (); + $at = $nt; + } + if ($nt <= $at) { + $best{$i} = 1; + } + if ($ndt == -1 || $nb < $ndt) { + %nxt = (); + $ndt = $nb; + } + if ($nb <= $ndt) { + $nxt{$i} = 1; + } + } + my @intersect = grep {exists $nxt{$_}} keys %best; + if (scalar @intersect == 0) { + push @out, $t; + } + } + return \@out; +} diff --git a/challenge-274/roger-bell-west/postscript/ch-1.ps b/challenge-274/roger-bell-west/postscript/ch-1.ps new file mode 100644 index 0000000000..09be170853 --- /dev/null +++ b/challenge-274/roger-bell-west/postscript/ch-1.ps @@ -0,0 +1,158 @@ +%!PS + +% begin included library code +% see https://codeberg.org/Firedrake/postscript-libraries/ +/strconcat % (a) (b) -> (ab) +{ + [ + 3 -1 roll + s2a aload length + 2 add -1 roll + s2a aload pop + ] a2s +} 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 + + +/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 + +/toset { % array -> dict of (value, true) + << exch + { + true + } forall + >> +} bind def + +/test.start { + print (:) print + /test.pass 0 def + /test.count 0 def +} 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 + +/enumerate.array { + 1 dict begin + /a exch def + [ + 0 1 a length 1 sub { + [ exch dup a exch get ] + } for + ] + 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 + +/s2a { + [ exch { } forall ] +} 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 + + +% end included library code + +/goatlatin { + 0 dict begin + /vowels (aeiouAEIOU) s2a toset def + [ exch + ( ) strsplit enumerate.array { + aload pop + /c exch s2a def + /i exch def + [ + c aload pop + vowels c 0 get known not { + c length -1 roll + } if + 109 + 97 + i 1 add { + 97 + } repeat + ] a2s + } forall + ] ( ) strjoin + end +} bind def + +(goatlatin) test.start +(I love Perl) goatlatin (Imaa ovelmaaa erlPmaaaa) eq test +(Perl and Raku are friends) goatlatin (erlPmaa andmaaa akuRmaaaa aremaaaaa riendsfmaaaaaa) eq test +(The Weekly Challenge) goatlatin (heTmaa eeklyWmaaa hallengeCmaaaa) eq test +test.end diff --git a/challenge-274/roger-bell-west/postscript/ch-2.ps b/challenge-274/roger-bell-west/postscript/ch-2.ps new file mode 100644 index 0000000000..f34399caf4 --- /dev/null +++ b/challenge-274/roger-bell-west/postscript/ch-2.ps @@ -0,0 +1,221 @@ +%!PS + +% begin included library code +% see https://codeberg.org/Firedrake/postscript-libraries/ +/test.start { + print (:) print + /test.pass 0 def + /test.count 0 def +} bind def + +/set.intersection { + 4 dict begin + /s 0 dict def + /b exch def + /a exch def + a keys { + /k exch def + b k known { + s k true put + } if + } forall + s + end +} 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 + +/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 + +/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 + +/listmin { + { min } reduce +} 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 + +/enumerate.array { + 1 dict begin + /a exch def + [ + 0 1 a length 1 sub { + [ exch dup a exch get ] + } for + ] + end +} bind def + +/filter { % array proc(bool) -> array + 1 dict begin + /p exch def + [ exch + { + dup p not + { + pop + } if + } forall + ] + end +} bind def + + +% end included library code + +/busroute { + 0 dict begin + /routes exch + [ exch + { + aload pop + /duration exch def + /offset exch def + /interval exch def + /ri 0 dict def + /start offset def + { + start offset 60 add gt { + exit + } if + ri start dup duration add put + /start start interval add def + } loop + ri + } forall + ] def + [ + 0 1 59 { + /t exch def + /best 0 dict def + /at -1 def + /nxt 0 dict def + /ndt -1 def + routes enumerate.array { + aload pop + /r exch def + /i exch def + /nb r keys { t ge } filter listmin def + /nt r nb get def + at -1 eq nt at lt or { + /best 0 dict def + /at nt def + } if + nt at le { + best i true put + } if + ndt -1 eq nb ndt lt or { + /nxt 0 dict def + /ndt nb def + } if + nb ndt le { + nxt i true put + } if + } forall + best nxt set.intersection length 0 eq { + t + } if + } for + ] + end +} bind def + +(busroute) test.start +[[12 11 41] [15 5 35]] busroute [36 37 38 39 40 41 42 43 44 45 46 47] deepeq test +[[12 3 41] [15 9 35] [30 5 25]] busroute [0 1 2 3 25 26 27 40 41 42 43 44 45 46 47 48 49 50 51 55 56 57 58 59] deepeq test +test.end diff --git a/challenge-274/roger-bell-west/python/ch-1.py b/challenge-274/roger-bell-west/python/ch-1.py new file mode 100755 index 0000000000..50bbf1ed06 --- /dev/null +++ b/challenge-274/roger-bell-west/python/ch-1.py @@ -0,0 +1,33 @@ +#! /usr/bin/python3 + +def goatlatin(a): + out = [] + for ix, word in enumerate(a.split(" ")): + nw = word + match word[0].lower(): + case 'a' | 'e' | 'i' | 'o' | 'u': + True + case _: + nw = word[1:] + nw += word[0] + nw += "ma" + for i in range(ix + 1): + nw += "a" + out.append(nw) + return " ".join(out) + + +import unittest + +class TestGoatlatin(unittest.TestCase): + + def test_ex1(self): + self.assertEqual(goatlatin("I love Perl"), "Imaa ovelmaaa erlPmaaaa", 'example 1') + + def test_ex2(self): + self.assertEqual(goatlatin("Perl and Raku are friends"), "erlPmaa andmaaa akuRmaaaa aremaaaaa riendsfmaaaaaa", 'example 2') + + def test_ex3(self): + self.assertEqual(goatlatin("The Weekly Challenge"), "heTmaa eeklyWmaaa hallengeCmaaaa", 'example 3') + +unittest.main() diff --git a/challenge-274/roger-bell-west/python/ch-2.py b/challenge-274/roger-bell-west/python/ch-2.py new file mode 100755 index 0000000000..fd00b3f58a --- /dev/null +++ b/challenge-274/roger-bell-west/python/ch-2.py @@ -0,0 +1,47 @@ +#! /usr/bin/python3 + +def busroute(a): + routes = [] + for rt in a: + ri = dict() + (interval, offset, duration) = rt + start = offset + while start <= 60 + offset: + ri[start] = start + duration + start += interval + routes.append(ri) + out = [] + for t in range(60): + best = set() + at = -1 + nxt = set() + ndt = -1 + for i, r in enumerate(routes): + nb = min([n for n in r.keys() if n >= t]) + nt = r[nb] + if at == -1 or nt < at: + best.clear() + at = nt + if nt <= at: + best.add(i) + if ndt == -1 or nb < ndt: + nxt.clear() + ndt = nb + if nb <= ndt: + nxt.add(i) + if len(best.intersection(nxt)) == 0: + out.append(t) + return out + + +import unittest + +class TestBusroute(unittest.TestCase): + + def test_ex1(self): + self.assertEqual(busroute([[12, 11, 41], [15, 5, 35]]), [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47], 'example 1') + + def test_ex2(self): + self.assertEqual(busroute([[12, 3, 41], [15, 9, 35], [30, 5, 25]]), [0, 1, 2, 3, 25, 26, 27, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59], 'example 2') + +unittest.main() diff --git a/challenge-274/roger-bell-west/raku/ch-1.p6 b/challenge-274/roger-bell-west/raku/ch-1.p6 new file mode 100755 index 0000000000..7b0840ed0e --- /dev/null +++ b/challenge-274/roger-bell-west/raku/ch-1.p6 @@ -0,0 +1,26 @@ +#! /usr/bin/raku + +use Test; + +plan 3; + +is(goatlatin('I love Perl'), 'Imaa ovelmaaa erlPmaaaa', 'example 1'); +is(goatlatin('Perl and Raku are friends'), 'erlPmaa andmaaa akuRmaaaa aremaaaaa riendsfmaaaaaa', 'example 2'); +is(goatlatin('The Weekly Challenge'), 'heTmaa eeklyWmaaa hallengeCmaaaa', 'example 3'); + +sub goatlatin($a) { + my @out; + my @w = $a.split(' '); + for @w.kv -> $ix, $word { + my @c = $word.comb; + my $nw = $word; + if (@c[0] !~~ m:i/<[aeiou]>/) { + @c.push(@c.shift); + $nw = @c.join(''); + } + $nw ~= 'ma'; + $nw ~= 'a' x ($ix + 1); + @out.push($nw); + } + return @out.join(' '); +} diff --git a/challenge-274/roger-bell-west/raku/ch-2.p6 b/challenge-274/roger-bell-west/raku/ch-2.p6 new file mode 100755 index 0000000000..e30c59ec5c --- /dev/null +++ b/challenge-274/roger-bell-west/raku/ch-2.p6 @@ -0,0 +1,51 @@ +#! /usr/bin/raku + +use Test; + +plan 2; + +is-deeply(busroute([[12, 11, 41], [15, 5, 35]]), [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47], 'example 1'); +is-deeply(busroute([[12, 3, 41], [15, 9, 35], [30, 5, 25]]), [0, 1, 2, 3, 25, 26, 27, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59], 'example 2'); + +sub busroute(@a) { + my @routes; + for @a -> @rt { + my %ri; + my ($interval, $offset, $duration) = @rt; + my $start = $offset; + while ($start <= 60 + $offset) { + %ri{$start} = $start + $duration; + $start += $interval; + } + @routes.push(%ri); + } + my @out; + for 0 .. 59 -> $t { + my %best = SetHash.new; + my $at = -1; + my %nxt = SetHash.new; + my $ndt = -1; + for @routes.kv -> $i, %r { + my $nb = %r.keys.grep({$_ >= $t}).min({ 0 + $_}); + my $nt = %r{$nb}; + if ($at == -1 || $nt < $at) { + %best = SetHash.new; + $at = $nt; + } + if ($nt <= $at) { + %best{$i}++; + } + if ($ndt == -1 || $nb < $ndt) { + %nxt = SetHash.new; + $ndt = $nb; + } + if ($nb <= $ndt) { + %nxt{$i}++ + } + } + if ((%best (&) %nxt).elems == 0) { + @out.push($t); + } + } + return @out; +} diff --git a/challenge-274/roger-bell-west/ruby/ch-1.rb b/challenge-274/roger-bell-west/ruby/ch-1.rb new file mode 100755 index 0000000000..136f23756a --- /dev/null +++ b/challenge-274/roger-bell-west/ruby/ch-1.rb @@ -0,0 +1,37 @@ +#! /usr/bin/ruby + +def goatlatin(a) + out = [] + a.split(" ").each_with_index do |word, ix| + c = word.split("") + if c[0] !~ /[aeiou]/i + co = c.shift; + c.push(co) + end + nw = c.join("") + nw += "ma" + 0.upto(ix) do + nw += "a" + end + out.push(nw) + end + return out.join(" ") +end + +require 'test/unit' + +class TestGoatlatin < Test::Unit::TestCase + + def test_ex1 + assert_equal('Imaa ovelmaaa erlPmaaaa', goatlatin('I love Perl')) + end + + def test_ex2 + assert_equal('erlPmaa andmaaa akuRmaaaa aremaaaaa riendsfmaaaaaa', goatlatin('Perl and Raku are friends')) + end + + def test_ex3 + assert_equal('heTmaa eeklyWmaaa hallengeCmaaaa', goatlatin('The Weekly Challenge')) + end + +end diff --git a/challenge-274/roger-bell-west/ruby/ch-2.rb b/challenge-274/roger-bell-west/ruby/ch-2.rb new file mode 100755 index 0000000000..6991fe90fe --- /dev/null +++ b/challenge-274/roger-bell-west/ruby/ch-2.rb @@ -0,0 +1,63 @@ +#! /usr/bin/ruby + +require 'set' + +def busroute(a) + route = [] + a.each do |rt| + ri = Hash.new + (interval, offset, duration) = rt + start = offset + while true do + if start > 60 + offset then + break + end + ri[start] = start + duration + start += interval + end + route.push(ri) + end + out = [] + 0.upto(59) do |t| + best = Set.new + at = -1 + nxt = Set.new + ndt = -1 + route.each_with_index do |r, i| + nb = r.keys.select { |n| n >= t }.min + nt = r[nb] + if at == -1 || nt < at + best = Set.new + at = nt + end + if nt <= at + best.add(i) + end + if ndt == -1 || nb < ndt + nxt = Set.new + ndt = nb + end + if nb <= ndt + nxt.add(i) + end + end + if (best & nxt) .length == 0 + out.push(t) + end + end + return out +end + +require 'test/unit' + +class TestBusroute < Test::Unit::TestCase + + def test_ex1 + assert_equal([36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47], busroute([[12, 11, 41], [15, 5, 35]])) + end + + def test_ex2 + assert_equal([0, 1, 2, 3, 25, 26, 27, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59], busroute([[12, 3, 41], [15, 9, 35], [30, 5, 25]])) + end + +end diff --git a/challenge-274/roger-bell-west/rust/ch-1.rs b/challenge-274/roger-bell-west/rust/ch-1.rs new file mode 100755 index 0000000000..0725ec20e0 --- /dev/null +++ b/challenge-274/roger-bell-west/rust/ch-1.rs @@ -0,0 +1,47 @@ +#! /bin/sh +//usr/bin/env rustc --test $0 -o ${0}x && ./${0}x --nocapture; rm -f ${0}x ; exit + +#[test] +fn test_ex1() { + assert_eq!(goatlatin("I love Perl"), "Imaa ovelmaaa erlPmaaaa"); +} + +#[test] +fn test_ex2() { + assert_eq!( + goatlatin("Perl and Raku are friends"), + "erlPmaa andmaaa akuRmaaaa aremaaaaa riendsfmaaaaaa" + ); +} + +#[test] +fn test_ex3() { + assert_eq!( + goatlatin("The Weekly Challenge"), + "heTmaa eeklyWmaaa hallengeCmaaaa" + ); +} + +fn goatlatin(a: &str) -> String { + let mut out = Vec::new(); + for (ix, word) in a.split(' ').enumerate() { + let mut c = word.chars().collect::>(); + let cc = c[0].to_ascii_lowercase(); + match cc { + 'a' | 'e' | 'i' | 'o' | 'u' => {} + _ => { + let co = c[0]; + let k = c.split_off(1); + c = k; + c.push(co); + } + }; + let mut nw = c.iter().collect::(); + nw.push_str("ma"); + for _ in 0..=ix { + nw.push('a'); + } + out.push(nw); + } + out.join(" ") +} diff --git a/challenge-274/roger-bell-west/rust/ch-2.rs b/challenge-274/roger-bell-west/rust/ch-2.rs new file mode 100755 index 0000000000..24d2145ebf --- /dev/null +++ b/challenge-274/roger-bell-west/rust/ch-2.rs @@ -0,0 +1,68 @@ +#! /bin/sh +//usr/bin/env rustc --test $0 -o ${0}x && ./${0}x --nocapture; rm -f ${0}x ; exit + +use std::collections::{HashMap, HashSet}; + +#[test] +fn test_ex1() { + assert_eq!( + busroute(vec![vec![12, 11, 41], vec![15, 5, 35]]), + vec![36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47] + ); +} + +#[test] +fn test_ex2() { + assert_eq!( + busroute(vec![vec![12, 3, 41], vec![15, 9, 35], vec![30, 5, 25]]), + vec![ + 0, 1, 2, 3, 25, 26, 27, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 55, 56, 57, 58, 59 + ] + ); +} + +fn busroute(a: Vec>) -> Vec { + let mut routes = Vec::new(); + for rt in a { + let mut ri = HashMap::new(); + let interval = rt[0]; + let offset = rt[1]; + let duration = rt[2]; + let mut start = offset; + while start <= 60 + offset { + ri.insert(start, start + duration); + start += interval; + } + routes.push(ri); + } + let mut out = Vec::new(); + for t in 0..60 { + let mut best = HashSet::new(); + let mut at: Option = None; + let mut nxt = HashSet::new(); + let mut ndt: Option = None; + for (i, r) in routes.iter().enumerate() { + let nb = r.keys().filter(|n| **n >= t).min().unwrap(); + let nt = r.get(nb).unwrap(); + if at.is_none() || *nt < at.unwrap() { + best.clear(); + at = Some(*nt); + } + if *nt <= at.unwrap() { + best.insert(i); + } + if ndt.is_none() || *nb < ndt.unwrap() { + nxt.clear(); + ndt = Some(*nb); + } + if *nb <= ndt.unwrap() { + nxt.insert(i); + } + } + if best.intersection(&nxt).count() == 0 { + out.push(t); + } + } + out +} diff --git a/challenge-274/roger-bell-west/scala/ch-1.scala b/challenge-274/roger-bell-west/scala/ch-1.scala new file mode 100644 index 0000000000..2eae2e585b --- /dev/null +++ b/challenge-274/roger-bell-west/scala/ch-1.scala @@ -0,0 +1,49 @@ +import scala.collection.mutable.ListBuffer + +object Goatlatin { + def is_vowel(c: Char): Boolean = { + return c.toLower match { + case 'a' | 'e' | 'i' | 'o' | 'u' => true + case _ => false + } + } + def goatlatin(a: String): String = { + var out = new ListBuffer[String]; + for ((word, i) <- a.split(" ").zipWithIndex){ + var c = word.toList + var nw = word; + if (!is_vowel(c(0))) { + var co = c.tail.to[ListBuffer]; + co += c.head; + nw = co.mkString; + } + nw += "ma"; + for (ix <- 0 to i) { + nw += "a"; + } + out += nw; + } + out.mkString(" ") + } + def main(args: Array[String]) { + if (goatlatin("I love Perl") == "Imaa ovelmaaa erlPmaaaa") { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (goatlatin("Perl and Raku are friends") == "erlPmaa andmaaa akuRmaaaa aremaaaaa riendsfmaaaaaa") { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (goatlatin("The Weekly Challenge") == "heTmaa eeklyWmaaa hallengeCmaaaa") { + print("Pass") + } else { + print("Fail") + } + println("") + + } +} diff --git a/challenge-274/roger-bell-west/scala/ch-2.scala b/challenge-274/roger-bell-west/scala/ch-2.scala new file mode 100644 index 0000000000..b24c81eac4 --- /dev/null +++ b/challenge-274/roger-bell-west/scala/ch-2.scala @@ -0,0 +1,65 @@ +import scala.collection.mutable +import scala.collection.mutable.ListBuffer + +object Busroute { + def busroute(a: List[List[Int]]): List[Int] = { + var route = new ListBuffer[mutable.Map[Int, Int]]; + for (rt <- a) { + var ri = mutable.Map.empty[Int, Int]; + val interval = rt(0); + val offset = rt(1); + val duration = rt(2); + var start = offset; + val end = 61 + offset; + while (start < end) { + ri += (start -> (start + duration)); + start += interval; + } + route += ri; + } + var out = new ListBuffer[Int]; + for (t <- 0 until 60) { + var best = mutable.Set.empty[Int]; + var at = -1; + var nxt = mutable.Set.empty[Int]; + var ndt = -1; + for ((r, i) <- route.zipWithIndex) { + val nb = r.keys.filter(n => n >= t).min; + val nt = r(nb); + if (at == -1 || nt < at) { + best.clear; + at = nt; + } + if (nt <= at) { + best += i; + } + if (ndt == -1 || nb < ndt) { + nxt.clear; + ndt = nb; + } + if (nb <= ndt) { + nxt += i; + } + } + if ((best & nxt).size == 0) { + out += t; + } + } + return out.toList; + } + def main(args: Array[String]) { + if (busroute(List(List(12, 11, 41), List(15, 5, 35))) == List(36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47)) { + print("Pass") + } else { + print("Fail") + } + print(" ") + if (busroute(List(List(12, 3, 41), List(15, 9, 35), List(30, 5, 25))) == List(0, 1, 2, 3, 25, 26, 27, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59)) { + print("Pass") + } else { + print("Fail") + } + println("") + + } +} diff --git a/challenge-274/roger-bell-west/tests.json b/challenge-274/roger-bell-west/tests.json new file mode 100644 index 0000000000..19f9a04763 --- /dev/null +++ b/challenge-274/roger-bell-west/tests.json @@ -0,0 +1,35 @@ +{ + "ch-1" : [ + { + "function" : "goatlatin", + "arguments" : "I love Perl", + "result" : "Imaa ovelmaaa erlPmaaaa" + }, + { + "arguments" : "Perl and Raku are friends", + "result" : "erlPmaa andmaaa akuRmaaaa aremaaaaa riendsfmaaaaaa" + }, + { + "arguments" : "The Weekly Challenge", + "result" : "heTmaa eeklyWmaaa hallengeCmaaaa" + } + ], + "ch-2" : [ + { + "function" : "busroute", + "arguments" : [ + [ 12, 11, 41 ], + [ 15, 5, 35 ] + ], + "result" : [ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47 ] + }, + { + "arguments" : [ + [ 12, 3, 41 ], + [ 15, 9, 35 ], + [ 30, 5, 25 ] + ], + "result" : [ 0, 1, 2, 3, 25, 26, 27, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 55, 56, 57, 58, 59 ] + } + ] +} -- cgit