aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Bell_West <roger@firedrake.org>2025-11-18 12:47:57 +0000
committerRoger Bell_West <roger@firedrake.org>2025-11-18 12:47:57 +0000
commit26432e1851dfcd8faf8b2b3f5b2d48ee5460302b (patch)
treea5951c99a91ff5cc634b696e539a14ec8ac5f905
parent25572447da12014ff4f20d22dcc3260e8a906f99 (diff)
downloadperlweeklychallenge-club-26432e1851dfcd8faf8b2b3f5b2d48ee5460302b.tar.gz
perlweeklychallenge-club-26432e1851dfcd8faf8b2b3f5b2d48ee5460302b.tar.bz2
perlweeklychallenge-club-26432e1851dfcd8faf8b2b3f5b2d48ee5460302b.zip
RogerBW solutions for challenge no. 348
-rwxr-xr-xchallenge-348/roger-bell-west/crystal/ch-1.cr39
-rwxr-xr-xchallenge-348/roger-bell-west/crystal/ch-2.cr40
-rwxr-xr-xchallenge-348/roger-bell-west/javascript/ch-1.js53
-rwxr-xr-xchallenge-348/roger-bell-west/javascript/ch-2.js54
-rw-r--r--challenge-348/roger-bell-west/kotlin/ch-1.kt60
-rw-r--r--challenge-348/roger-bell-west/kotlin/ch-2.kt55
-rwxr-xr-xchallenge-348/roger-bell-west/lua/ch-1.lua75
-rwxr-xr-xchallenge-348/roger-bell-west/lua/ch-2.lua57
-rwxr-xr-xchallenge-348/roger-bell-west/perl/ch-1.pl33
-rwxr-xr-xchallenge-348/roger-bell-west/perl/ch-2.pl33
-rw-r--r--challenge-348/roger-bell-west/postscript/ch-1.ps100
-rw-r--r--challenge-348/roger-bell-west/postscript/ch-2.ps99
-rwxr-xr-xchallenge-348/roger-bell-west/python/ch-1.py39
-rwxr-xr-xchallenge-348/roger-bell-west/python/ch-2.py38
-rwxr-xr-xchallenge-348/roger-bell-west/raku/ch-1.p630
-rwxr-xr-xchallenge-348/roger-bell-west/raku/ch-2.p631
-rwxr-xr-xchallenge-348/roger-bell-west/ruby/ch-1.rb46
-rwxr-xr-xchallenge-348/roger-bell-west/ruby/ch-2.rb47
-rwxr-xr-xchallenge-348/roger-bell-west/rust/ch-1.rs49
-rwxr-xr-xchallenge-348/roger-bell-west/rust/ch-2.rs47
-rw-r--r--challenge-348/roger-bell-west/scala/ch-1.scala63
-rw-r--r--challenge-348/roger-bell-west/scala/ch-2.scala57
-rw-r--r--challenge-348/roger-bell-west/tests.json68
-rw-r--r--challenge-348/roger-bell-west/typst/ch-1.typ44
-rw-r--r--challenge-348/roger-bell-west/typst/ch-2.typ43
25 files changed, 1300 insertions, 0 deletions
diff --git a/challenge-348/roger-bell-west/crystal/ch-1.cr b/challenge-348/roger-bell-west/crystal/ch-1.cr
new file mode 100755
index 0000000000..5e2187bc75
--- /dev/null
+++ b/challenge-348/roger-bell-west/crystal/ch-1.cr
@@ -0,0 +1,39 @@
+#! /usr/bin/crystal
+
+def stringalike(a)
+ if a.size % 2 == 1
+ return false
+ end
+ vt = 0
+ mode = 1
+ av = false
+ a.downcase.chars.each_with_index do |c, i|
+ if i * 2 == a.size
+ mode = -1
+ end
+ if c.in_set?("aeiou")
+ vt += mode
+ av = true
+ end
+ end
+ av && (vt == 0)
+end
+
+require "spec"
+describe "stringalike" do
+ it "test_ex1" do
+ stringalike("textbook").should eq false
+ end
+ it "test_ex2" do
+ stringalike("book").should eq true
+ end
+ it "test_ex3" do
+ stringalike("AbCdEfGh").should eq true
+ end
+ it "test_ex4" do
+ stringalike("rhythmmyth").should eq false
+ end
+ it "test_ex5" do
+ stringalike("UmpireeAudio").should eq false
+ end
+end
diff --git a/challenge-348/roger-bell-west/crystal/ch-2.cr b/challenge-348/roger-bell-west/crystal/ch-2.cr
new file mode 100755
index 0000000000..1596e0e5e7
--- /dev/null
+++ b/challenge-348/roger-bell-west/crystal/ch-2.cr
@@ -0,0 +1,40 @@
+#! /usr/bin/crystal
+
+def hm2m(a)
+ p = a.split(":")
+ return p[0].to_i * 60 + p[1].to_i
+end
+
+def converttime(ssrc, ttgt)
+ src = hm2m(ssrc)
+ tgt = hm2m(ttgt)
+ if tgt < src
+ tgt += 24 * 60
+ end
+ delta = tgt - src
+ oc = 0
+ [60, 15, 5, 1].each do |op|
+ q, delta = delta.divmod(op)
+ oc += q
+ end
+ oc
+end
+
+require "spec"
+describe "converttime" do
+ it "test_ex1" do
+ converttime("02:30", "02:45").should eq 1
+ end
+ it "test_ex2" do
+ converttime("11:55", "12:15").should eq 2
+ end
+ it "test_ex3" do
+ converttime("09:00", "13:00").should eq 4
+ end
+ it "test_ex4" do
+ converttime("23:45", "00:30").should eq 3
+ end
+ it "test_ex5" do
+ converttime("14:20", "15:25").should eq 2
+ end
+end
diff --git a/challenge-348/roger-bell-west/javascript/ch-1.js b/challenge-348/roger-bell-west/javascript/ch-1.js
new file mode 100755
index 0000000000..3a4f6ce6cd
--- /dev/null
+++ b/challenge-348/roger-bell-west/javascript/ch-1.js
@@ -0,0 +1,53 @@
+#! /usr/bin/node
+
+"use strict"
+
+function stringalike(a) {
+ if (a.length % 2 == 1) {
+ return false;
+ }
+ let vt = 0;
+ let mode = 1;
+ let av = false;
+ a.toLowerCase().split("").forEach((c, i) => {
+ if (i * 2 == a.length) {
+ mode = -1;
+ }
+ if (c.match(/[aeiou]/)) {
+ av = true;
+ vt += mode;
+ }
+ });
+ return av && (vt == 0);
+}
+
+if (!stringalike('textbook')) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (stringalike('book')) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (stringalike('AbCdEfGh')) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (!stringalike('rhythmmyth')) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (!stringalike('UmpireeAudio')) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-348/roger-bell-west/javascript/ch-2.js b/challenge-348/roger-bell-west/javascript/ch-2.js
new file mode 100755
index 0000000000..22d55a17c9
--- /dev/null
+++ b/challenge-348/roger-bell-west/javascript/ch-2.js
@@ -0,0 +1,54 @@
+#! /usr/bin/node
+
+"use strict"
+
+function hm2m(a) {
+ const p = a.match(/(\d+):(\d+)/);
+ return parseInt(p[1]) * 60 + parseInt(p[2]);
+}
+
+function converttime(ssrc, ttgt) {
+ const src = hm2m(ssrc);
+ let tgt = hm2m(ttgt);
+ if (tgt < src) {
+ tgt += 24 * 60;
+ }
+ let delta = tgt - src;
+ let oc = 0;
+ for (let op of [60, 15, 5, 1]) {
+ oc += Math.floor(delta / op);
+ delta %= op;
+ }
+ return oc;
+}
+
+if (converttime('02:30', '02:45') == 1) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (converttime('11:55', '12:15') == 2) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (converttime('09:00', '13:00') == 4) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (converttime('23:45', '00:30') == 3) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (converttime('14:20', '15:25') == 2) {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-348/roger-bell-west/kotlin/ch-1.kt b/challenge-348/roger-bell-west/kotlin/ch-1.kt
new file mode 100644
index 0000000000..d496da8f75
--- /dev/null
+++ b/challenge-348/roger-bell-west/kotlin/ch-1.kt
@@ -0,0 +1,60 @@
+fun is_vowel(c: Char): Boolean {
+ return when (c.lowercaseChar()) {
+ 'a', 'e', 'i', 'o', 'u' -> true
+ else -> false
+ }
+}
+
+fun stringalike(a: String): Boolean {
+ if (a.length % 2 == 1) {
+ return false
+ }
+ var vt = 0
+ var mode = 1
+ var av = false
+ a.toList().forEachIndexed { i, c ->
+ if (i * 2 == a.length) {
+ mode = -1
+ }
+ if (is_vowel(c)) {
+ av = true
+ vt += mode
+ }
+ }
+ return av && (vt == 0)
+}
+
+fun main() {
+
+ if (!stringalike("textbook")) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (stringalike("book")) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (stringalike("AbCdEfGh")) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (!stringalike("rhythmmyth")) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (!stringalike("UmpireeAudio")) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-348/roger-bell-west/kotlin/ch-2.kt b/challenge-348/roger-bell-west/kotlin/ch-2.kt
new file mode 100644
index 0000000000..7bbcd303be
--- /dev/null
+++ b/challenge-348/roger-bell-west/kotlin/ch-2.kt
@@ -0,0 +1,55 @@
+
+fun hm2m(a: String): Int {
+ val p = a.split(":")
+ return p[0].toInt() * 60 + p[1].toInt()
+}
+
+fun converttime(ssrc: String, ttgt: String): Int {
+ val src = hm2m(ssrc)
+ var tgt = hm2m(ttgt)
+ if (tgt < src) {
+ tgt += 24 * 60
+ }
+ var delta: Int = tgt - src
+ var oc = 0
+ for (op in listOf(60, 15, 5, 1)) {
+ oc += delta / op
+ delta %= op
+ }
+ return oc
+}
+
+fun main() {
+
+ if (converttime("02:30", "02:45") == 1) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (converttime("11:55", "12:15") == 2) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (converttime("09:00", "13:00") == 4) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (converttime("23:45", "00:30") == 3) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (converttime("14:20", "15:25") == 2) {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ println("")
+
+}
diff --git a/challenge-348/roger-bell-west/lua/ch-1.lua b/challenge-348/roger-bell-west/lua/ch-1.lua
new file mode 100755
index 0000000000..3261a885d6
--- /dev/null
+++ b/challenge-348/roger-bell-west/lua/ch-1.lua
@@ -0,0 +1,75 @@
+#! /usr/bin/lua
+
+function split(t)
+ local cl = {}
+ string.gsub(t,
+ "(.)",
+ function(c)
+ table.insert(cl, c)
+ end
+ )
+ return cl
+end
+
+function is_vowel(c)
+ if string.find(c, "[aeiou]") == 1 then
+ return true
+ else
+ return false
+ end
+end
+
+function stringalike(a)
+ if #a % 2 == 1 then
+ return false
+ end
+ local vt = 0
+ local mode = 1
+ local av = false
+ for i,c in ipairs(split(string.lower(a))) do
+ if is_vowel(c) then
+ av = true
+ vt = vt + mode
+ end
+ if i * 2 == #a then
+ mode = -1
+ end
+ end
+ return av and (vt == 0)
+end
+
+if not stringalike("textbook") then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if stringalike("book") then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if stringalike("AbCdEfGh") then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if not stringalike("rhythmmyth") then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if not stringalike("UmpireeAudio") then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-348/roger-bell-west/lua/ch-2.lua b/challenge-348/roger-bell-west/lua/ch-2.lua
new file mode 100755
index 0000000000..c8c13ba2c4
--- /dev/null
+++ b/challenge-348/roger-bell-west/lua/ch-2.lua
@@ -0,0 +1,57 @@
+#! /usr/bin/lua
+
+function hm2m(a)
+ local h, m = string.match(a, "^(%d+):(%d+)$")
+ return h * 60 + m
+end
+
+function converttime(ssrc, ttgt)
+ local src = hm2m(ssrc)
+ local tgt = hm2m(ttgt)
+ if tgt < src then
+ tgt = tgt + 24 * 60
+ end
+ local delta = tgt - src
+ local oc = 0
+ for _, op in ipairs({60, 15, 5, 1}) do
+ oc = oc + delta // op
+ delta = delta % op
+ end
+ return oc
+end
+
+if converttime("02:30", "02:45") == 1 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if converttime("11:55", "12:15") == 2 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if converttime("09:00", "13:00") == 4 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if converttime("23:45", "00:30") == 3 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+io.write(" ")
+
+if converttime("14:20", "15:25") == 2 then
+ io.write("Pass")
+else
+ io.write("FAIL")
+end
+print("")
+
diff --git a/challenge-348/roger-bell-west/perl/ch-1.pl b/challenge-348/roger-bell-west/perl/ch-1.pl
new file mode 100755
index 0000000000..a520a2353e
--- /dev/null
+++ b/challenge-348/roger-bell-west/perl/ch-1.pl
@@ -0,0 +1,33 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 5;
+
+is(stringalike('textbook'), 0, 'example 1');
+is(stringalike('book'), 1, 'example 2');
+is(stringalike('AbCdEfGh'), 1, 'example 3');
+is(stringalike('rhythmmyth'), 0, 'example 4');
+is(stringalike('UmpireeAudio'), 0, 'example 5');
+
+sub stringalike($a) {
+ if (length($a) % 2 == 1) {
+ return 0;
+ }
+ my $vt = 0;
+ my $mode = 1;
+ my $av = 0;
+ my @sa = split('', lc($a));
+ while (my ($i, $c) = each @sa) {
+ if ($i * 2 == length($a)) {
+ $mode = -1;
+ }
+ if ($c =~ /[aeiou]/) {
+ $av = 1;
+ $vt += $mode;
+ }
+ }
+ ($av && ($vt == 0))?1:0;
+}
diff --git a/challenge-348/roger-bell-west/perl/ch-2.pl b/challenge-348/roger-bell-west/perl/ch-2.pl
new file mode 100755
index 0000000000..07311837b9
--- /dev/null
+++ b/challenge-348/roger-bell-west/perl/ch-2.pl
@@ -0,0 +1,33 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use experimental 'signatures';
+
+use Test::More tests => 5;
+
+is(converttime('02:30', '02:45'), 1, 'example 1');
+is(converttime('11:55', '12:15'), 2, 'example 2');
+is(converttime('09:00', '13:00'), 4, 'example 3');
+is(converttime('23:45', '00:30'), 3, 'example 4');
+is(converttime('14:20', '15:25'), 2, 'example 5');
+
+sub hm2m($a) {
+ $a =~ /(\d+):(\d+)/;
+ $1 * 60 + $2;
+}
+
+sub converttime($ssrc, $ttgt) {
+ my $src = hm2m($ssrc);
+ my $tgt = hm2m($ttgt);
+ if ($tgt < $src) {
+ $tgt += 24 * 60;
+ }
+ my $delta = $tgt - $src;
+ my $oc = 0;
+ foreach my $op (60, 15, 5, 1) {
+ $oc += int($delta / $op);
+ $delta %= $op;
+ }
+ $oc;
+}
diff --git a/challenge-348/roger-bell-west/postscript/ch-1.ps b/challenge-348/roger-bell-west/postscript/ch-1.ps
new file mode 100644
index 0000000000..5b924f038d
--- /dev/null
+++ b/challenge-348/roger-bell-west/postscript/ch-1.ps
@@ -0,0 +1,100 @@
+%!PS
+
+% begin included library code
+% see https://codeberg.org/Firedrake/postscript-libraries/
+/enumerate.array {
+ 1 dict begin
+ /a exch def
+ [
+ 0 1 a length 1 sub {
+ [ exch dup a exch get ]
+ } for
+ ]
+ end
+} 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
+
+/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
+
+/s2a {
+ [ exch { } forall ]
+} bind def
+
+
+% end included library code
+
+/is_vowel {
+ << 65 true
+ 69 true
+ 73 true
+ 79 true
+ 85 true
+ 97 true
+ 101 true
+ 105 true
+ 111 true
+ 117 true >>
+ exch known
+} bind def
+
+/stringalike {
+ 0 dict begin
+ /a exch def
+ a length 2 mod 1 eq {
+ false
+ } {
+ /vt 0 def
+ /mode 1 def
+ /av false def
+ a s2a enumerate.array dup {
+ aload pop
+ /c exch def
+ /i exch def
+ i 2 mul a length eq {
+ /mode -1 def
+ } if
+ c is_vowel {
+ /av true def
+ /vt vt mode add def
+ } if
+ } forall
+ vt 0 eq av and
+ } ifelse
+ end
+} bind def
+
+(stringalike) test.start
+(textbook) stringalike not test
+(book) stringalike test
+(AbCdEfGh) stringalike test
+(rhythmmyth) stringalike not test
+(UmpireeAudio) stringalike not test
+test.end
diff --git a/challenge-348/roger-bell-west/postscript/ch-2.ps b/challenge-348/roger-bell-west/postscript/ch-2.ps
new file mode 100644
index 0000000000..9e31173987
--- /dev/null
+++ b/challenge-348/roger-bell-west/postscript/ch-2.ps
@@ -0,0 +1,99 @@
+%!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
+
+/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
+
+/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
+
+/test.start {
+ print (:) print
+ /test.pass 0 def
+ /test.count 0 def
+} bind def
+
+
+% end included library code
+
+/hm2m {
+ (:) strsplit
+ aload pop
+ cvi
+ exch
+ cvi
+ 60 mul
+ add
+} bind def
+
+/converttime {
+ 0 dict begin
+ hm2m /tgt exch def
+ hm2m /src exch def
+ tgt src lt {
+ /tgt tgt 24 60 mul add def
+ } if
+ /delta tgt src sub def
+ /oc 0 def
+ [ 60 15 5 1 ] {
+ /op exch def
+ /oc oc delta op idiv add def
+ /delta delta op mod def
+ } forall
+ oc
+ end
+} bind def
+
+(converttime) test.start
+(02:30) (02:45) converttime 1 eq test
+(11:55) (12:15) converttime 2 eq test
+(09:00) (13:00) converttime 4 eq test
+(23:45) (00:30) converttime 3 eq test
+(14:20) (15:25) converttime 2 eq test
+test.end
diff --git a/challenge-348/roger-bell-west/python/ch-1.py b/challenge-348/roger-bell-west/python/ch-1.py
new file mode 100755
index 0000000000..7dd8dec8f4
--- /dev/null
+++ b/challenge-348/roger-bell-west/python/ch-1.py
@@ -0,0 +1,39 @@
+#! /usr/bin/python3
+
+import re
+
+def stringalike(a):
+ if len(a) % 2 == 1:
+ return false
+ vt = 0
+ mode = 1
+ av = False
+ rx = re.compile("[aeiou]")
+ for i, c in enumerate(a.lower()):
+ if i * 2 == len(a):
+ mode = -1
+ if re.match(rx, c):
+ av = True
+ vt += mode
+ return av and (vt == 0)
+
+import unittest
+
+class TestStringalike(unittest.TestCase):
+
+ def test_ex1(self):
+ self.assertEqual(stringalike("textbook"), False, 'example 1')
+
+ def test_ex2(self):
+ self.assertEqual(stringalike("book"), True, 'example 2')
+
+ def test_ex3(self):
+ self.assertEqual(stringalike("AbCdEfGh"), True, 'example 3')
+
+ def test_ex4(self):
+ self.assertEqual(stringalike("rhythmmyth"), False, 'example 4')
+
+ def test_ex5(self):
+ self.assertEqual(stringalike("UmpireeAudio"), False, 'example 5')
+
+unittest.main()
diff --git a/challenge-348/roger-bell-west/python/ch-2.py b/challenge-348/roger-bell-west/python/ch-2.py
new file mode 100755
index 0000000000..8f3827b8fd
--- /dev/null
+++ b/challenge-348/roger-bell-west/python/ch-2.py
@@ -0,0 +1,38 @@
+#! /usr/bin/python3
+
+def hm2m(a):
+ p = a.split(":")
+ return int(p[0]) * 60 + int(p[1])
+
+def converttime(ssrc, ttgt):
+ src = hm2m(ssrc)
+ tgt = hm2m(ttgt)
+ if tgt < src:
+ tgt += 24 * 60
+ delta = tgt - src
+ oc = 0
+ for op in [60, 15, 5, 1]:
+ oc += delta // op
+ delta %= op
+ return oc
+
+import unittest
+
+class TestConverttime(unittest.TestCase):
+
+ def test_ex1(self):
+ self.assertEqual(converttime("02:30", "02:45"), 1, 'example 1')
+
+ def test_ex2(self):
+ self.assertEqual(converttime("11:55", "12:15"), 2, 'example 2')
+
+ def test_ex3(self):
+ self.assertEqual(converttime("09:00", "13:00"), 4, 'example 3')
+
+ def test_ex4(self):
+ self.assertEqual(converttime("23:45", "00:30"), 3, 'example 4')
+
+ def test_ex5(self):
+ self.assertEqual(converttime("14:20", "15:25"), 2, 'example 5')
+
+unittest.main()
diff --git a/challenge-348/roger-bell-west/raku/ch-1.p6 b/challenge-348/roger-bell-west/raku/ch-1.p6
new file mode 100755
index 0000000000..047db6d5bb
--- /dev/null
+++ b/challenge-348/roger-bell-west/raku/ch-1.p6
@@ -0,0 +1,30 @@
+#! /usr/bin/raku
+
+use Test;
+
+plan 5;
+
+is(stringalike('textbook'), False, 'example 1');
+is(stringalike('book'), True, 'example 2');
+is(stringalike('AbCdEfGh'), True, 'example 3');
+is(stringalike('rhythmmyth'), False, 'example 4');
+is(stringalike('UmpireeAudio'), False, 'example 5');
+
+sub stringalike($a) {
+ if ($a.chars % 2 == 1) {
+ return False;
+ }
+ my $vt = 0;
+ my $mode = 1;
+ my $av = False;
+ for $a.lc.comb.kv -> $i, $c {
+ if ($i * 2 == $a.chars) {
+ $mode = -1;
+ }
+ if ($c ~~ /<[aeiou]>/) {
+ $av = True;
+ $vt += $mode;
+ }
+ }
+ $av && ($vt == 0);
+}
diff --git a/challenge-348/roger-bell-west/raku/ch-2.p6 b/challenge-348/roger-bell-west/raku/ch-2.p6
new file mode 100755
index 0000000000..11f38e6b13
--- /dev/null
+++ b/challenge-348/roger-bell-west/raku/ch-2.p6
@@ -0,0 +1,31 @@
+#! /usr/bin/raku
+
+use Test;
+
+plan 5;
+
+is(converttime('02:30', '02:45'), 1, 'example 1');
+is(converttime('11:55', '12:15'), 2, 'example 2');
+is(converttime('09:00', '13:00'), 4, 'example 3');
+is(converttime('23:45', '00:30'), 3, 'example 4');
+is(converttime('14:20', '15:25'), 2, 'example 5');
+
+sub hm2m($a) {
+ my @p = $a.comb(/\d+/);
+ @p[0] * 60 + @p[1];
+}
+
+sub converttime($ssrc, $ttgt) {
+ my $src = hm2m($ssrc);
+ my $tgt = hm2m($ttgt);
+ if ($tgt < $src) {
+ $tgt += 24 * 60;
+ }
+ my $delta = $tgt - $src;
+ my $oc = 0;
+ for [60, 15, 5, 1] -> $op {
+ $oc += $delta div $op;
+ $delta %= $op;
+ }
+ $oc;
+}
diff --git a/challenge-348/roger-bell-west/ruby/ch-1.rb b/challenge-348/roger-bell-west/ruby/ch-1.rb
new file mode 100755
index 0000000000..3869587766
--- /dev/null
+++ b/challenge-348/roger-bell-west/ruby/ch-1.rb
@@ -0,0 +1,46 @@
+#! /usr/bin/ruby
+
+def stringalike(a)
+ if a.size % 2 == 1
+ return false
+ end
+ vt = 0
+ mode = 1
+ av = false
+ a.downcase.chars.each_with_index do |c, i|
+ if i * 2 == a.size
+ mode = -1
+ end
+ if c =~ /[aeiou]/
+ vt += mode
+ av = true
+ end
+ end
+ av && (vt == 0)
+end
+
+require 'test/unit'
+
+class TestStringalike < Test::Unit::TestCase
+
+ def test_ex1
+ assert_equal(false, stringalike('textbook'))
+ end
+
+ def test_ex2
+ assert_equal(true, stringalike('book'))
+ end
+
+ def test_ex3
+ assert_equal(true, stringalike('AbCdEfGh'))
+ end
+
+ def test_ex4
+ assert_equal(false, stringalike('rhythmmyth'))
+ end
+
+ def test_ex5
+ assert_equal(false, stringalike('UmpireeAudio'))
+ end
+
+end
diff --git a/challenge-348/roger-bell-west/ruby/ch-2.rb b/challenge-348/roger-bell-west/ruby/ch-2.rb
new file mode 100755
index 0000000000..b11fa066b6
--- /dev/null
+++ b/challenge-348/roger-bell-west/ruby/ch-2.rb
@@ -0,0 +1,47 @@
+#! /usr/bin/ruby
+
+def hm2m(a)
+ p = a.split(":")
+ return p[0].to_i * 60 + p[1].to_i
+end
+
+def converttime(ssrc, ttgt)
+ src = hm2m(ssrc)
+ tgt = hm2m(ttgt)
+ if tgt < src
+ tgt += 24 * 60
+ end
+ delta = tgt - src
+ oc = 0
+ [60, 15, 5, 1].each do |op|
+ q, delta = delta.divmod(op)
+ oc += q
+ end
+ oc
+end
+
+require 'test/unit'
+
+class TestConverttime < Test::Unit::TestCase
+
+ def test_ex1
+ assert_equal(1, converttime('02:30', '02:45'))
+ end
+
+ def test_ex2
+ assert_equal(2, converttime('11:55', '12:15'))
+ end
+
+ def test_ex3
+ assert_equal(4, converttime('09:00', '13:00'))
+ end
+
+ def test_ex4
+ assert_equal(3, converttime('23:45', '00:30'))
+ end
+
+ def test_ex5
+ assert_equal(2, converttime('14:20', '15:25'))
+ end
+
+end
diff --git a/challenge-348/roger-bell-west/rust/ch-1.rs b/challenge-348/roger-bell-west/rust/ch-1.rs
new file mode 100755
index 0000000000..36d4205eb9
--- /dev/null
+++ b/