aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Jacoby <jacoby.david@gmail.com>2024-03-06 12:20:54 -0500
committerGitHub <noreply@github.com>2024-03-06 12:20:54 -0500
commitc2236d751700d5f259791a9218696e934c6bebdc (patch)
tree49838dee91b2ad0a2c5b22ad8de0937bd68d6111
parentdd68c49c478d198ce7f22ec6961fe4d0bb77376e (diff)
parent38ae28aaeacfc9dd53e892f94d5e83d4a83395d2 (diff)
downloadperlweeklychallenge-club-c2236d751700d5f259791a9218696e934c6bebdc.tar.gz
perlweeklychallenge-club-c2236d751700d5f259791a9218696e934c6bebdc.tar.bz2
perlweeklychallenge-club-c2236d751700d5f259791a9218696e934c6bebdc.zip
Merge branch 'manwar:master' into master
-rwxr-xr-xchallenge-259/eric-cheung/python/ch-1.py23
-rwxr-xr-xchallenge-259/eric-cheung/python/ch-2.py57
-rw-r--r--challenge-259/mark-anderson/raku/ch-1.raku55
-rw-r--r--challenge-259/mark-anderson/raku/ch-2.raku29
-rw-r--r--challenge-259/peter-campbell-smith/blog.txt1
-rwxr-xr-xchallenge-259/peter-campbell-smith/perl/ch-1.pl159
-rwxr-xr-xchallenge-259/peter-campbell-smith/perl/ch-2.pl59
-rwxr-xr-xchallenge-259/peter-meszaros/perl/ch-1.pl61
-rwxr-xr-xchallenge-259/peter-meszaros/perl/ch-2.pl99
-rwxr-xr-xchallenge-259/roger-bell-west/javascript/ch-1.js30
-rw-r--r--challenge-259/roger-bell-west/kotlin/ch-1.kt32
-rwxr-xr-xchallenge-259/roger-bell-west/perl/ch-1.pl30
-rw-r--r--challenge-259/roger-bell-west/postscript/ch-1.ps200
-rwxr-xr-xchallenge-259/roger-bell-west/python/ch-1.py25
-rwxr-xr-xchallenge-259/roger-bell-west/raku/ch-1.p625
-rwxr-xr-xchallenge-259/roger-bell-west/ruby/ch-1.rb34
-rwxr-xr-xchallenge-259/roger-bell-west/rust/ch-1.rs41
-rwxr-xr-xchallenge-259/roger-bell-west/rust/ch-2.rs123
-rw-r--r--challenge-259/roger-bell-west/scala/ch-1.scala32
-rw-r--r--challenge-259/roger-bell-west/tests.yaml15
-rw-r--r--challenge-259/spadacciniweb/elixir/ch-1.exs57
-rw-r--r--challenge-259/spadacciniweb/go/ch-1.go80
-rw-r--r--challenge-259/spadacciniweb/perl/ch-1.pl76
-rw-r--r--challenge-259/spadacciniweb/python/ch-1.py54
-rw-r--r--challenge-259/spadacciniweb/ruby/ch-1.rb56
-rw-r--r--challenge-259/wlmb/blog.txt1
-rwxr-xr-xchallenge-259/wlmb/perl/ch-1.pl40
-rwxr-xr-xchallenge-259/wlmb/perl/ch-2.pl40
-rw-r--r--stats/pwc-current.json226
-rw-r--r--stats/pwc-language-breakdown-summary.json74
-rw-r--r--stats/pwc-language-breakdown.json3546
-rw-r--r--stats/pwc-leaders.json482
-rw-r--r--stats/pwc-summary-1-30.json102
-rw-r--r--stats/pwc-summary-121-150.json98
-rw-r--r--stats/pwc-summary-151-180.json46
-rw-r--r--stats/pwc-summary-181-210.json94
-rw-r--r--stats/pwc-summary-211-240.json100
-rw-r--r--stats/pwc-summary-241-270.json104
-rw-r--r--stats/pwc-summary-271-300.json40
-rw-r--r--stats/pwc-summary-301-330.json48
-rw-r--r--stats/pwc-summary-31-60.json100
-rw-r--r--stats/pwc-summary-61-90.json58
-rw-r--r--stats/pwc-summary-91-120.json106
-rw-r--r--stats/pwc-summary.json52
44 files changed, 4222 insertions, 2588 deletions
diff --git a/challenge-259/eric-cheung/python/ch-1.py b/challenge-259/eric-cheung/python/ch-1.py
new file mode 100755
index 0000000000..794b79e029
--- /dev/null
+++ b/challenge-259/eric-cheung/python/ch-1.py
@@ -0,0 +1,23 @@
+
+from datetime import datetime, timedelta
+
+strDateFormat = "%Y-%m-%d"
+
+## Example 1
+## strStartDate = "2018-06-28"
+## nOffset = 3
+## arrBankHoliday = ["2018-07-03"]
+
+## Example 2
+strStartDate = "2018-06-28"
+nOffset = 3
+arrBankHoliday = []
+
+objOutputDate = datetime.strptime(strStartDate, strDateFormat)
+
+while nOffset > 0:
+ objOutputDate = objOutputDate + timedelta(days = 1)
+ if objOutputDate.weekday() < 5 and not objOutputDate.strftime(strDateFormat) in arrBankHoliday:
+ nOffset = nOffset - 1
+
+print (objOutputDate.strftime(strDateFormat))
diff --git a/challenge-259/eric-cheung/python/ch-2.py b/challenge-259/eric-cheung/python/ch-2.py
new file mode 100755
index 0000000000..271db58f8a
--- /dev/null
+++ b/challenge-259/eric-cheung/python/ch-2.py
@@ -0,0 +1,57 @@
+
+## Remarks
+## https://stackoverflow.com/questions/74569246/replace-space-in-between-double-quote-to-underscore
+
+import json
+import re
+
+def GetDoubleQuote (strInput):
+ if strInput[0] == "\"":
+ return strInput
+ return "\"" + strInput + "\""
+
+def repl(strInput):
+ return strInput[0].replace(' ', '^')
+
+
+## strLineInput = '{% id field1="value1" field2="value2" field3=42 %}' ## Example 1
+## strLineInput = '{% youtube title="Title \"quoted\" done" %}' ## Example 2
+## strLineInput = '{% youtube title="Title quoted done" %}' ## Example 3
+## strLineInput = '{% youtube title="Title with escaped backslash \\" %}' ## Example 4
+## strLineInput = '{% id %}' ## Example 5
+strLineInput = '''
+{% id field1="value1" field2="value2" field3=42 %}
+LINES
+{% endid %}
+''' ## Example 6
+
+bMultipleLine = False
+arrMultipleLineSplit = strLineInput.split("\n")
+
+if len(arrMultipleLineSplit) > 1:
+ bMultipleLine = True
+ strLineInput = arrMultipleLineSplit[1]
+
+strReplacePattern = re.compile(r'\"[^\"]+\"')
+strLineInput = re.sub(strReplacePattern, repl, strLineInput)
+
+arrLineSplit = strLineInput.replace("%", "").split()
+arrLineSplit = [elemLoop.replace('^', ' ') for elemLoop in arrLineSplit]
+
+arrLineSplit[1] = GetDoubleQuote("name") + " : " + GetDoubleQuote(arrLineSplit[1])
+for nIndx in range(2, len(arrLineSplit) - 1):
+ arrLineSplit[nIndx] = " : ".join([GetDoubleQuote(elemLoop) if nIndx == 0 else elemLoop for nIndx, elemLoop in enumerate(arrLineSplit[nIndx].split("="))])
+
+strJsonOutput = "{" + arrLineSplit[1]
+if len(arrLineSplit) > 3:
+ strJsonOutput = strJsonOutput + ", " + GetDoubleQuote("fields") + " : " + "{" + ", ".join(arrLineSplit[2:-1]) + "}"
+
+if bMultipleLine:
+ strJsonOutput = strJsonOutput + ", " + GetDoubleQuote("text") + " : " + GetDoubleQuote(arrMultipleLineSplit[2])
+
+strJsonOutput = strJsonOutput + "}"
+
+## print (arrLineSplit)
+## print (strJsonOutput)
+print (json.loads(strJsonOutput))
+## print (json.loads(strJsonOutput)["name"])
diff --git a/challenge-259/mark-anderson/raku/ch-1.raku b/challenge-259/mark-anderson/raku/ch-1.raku
index 26c0180e8e..f49f9b330b 100644
--- a/challenge-259/mark-anderson/raku/ch-1.raku
+++ b/challenge-259/mark-anderson/raku/ch-1.raku
@@ -4,10 +4,63 @@ use Test;
is banking-day-offset('2018-06-28', 3), '2018-07-03';
is banking-day-offset('2018-06-28', 3, ['2018-07-03']), '2018-07-04';
is banking-day-offset('2018-06-30', 0), '2018-07-02';
-is banking-day-offset('2018-06-30', 8, ['2018-07-04', '2018-07-03']), '2018-07-16';
is banking-day-offset('2018-07-02', 0), '2018-07-02';
+is banking-day-offset('2018-06-30', 8, ['2018-07-04', '2018-07-03']), '2018-07-16';
is banking-day-offset('2018-07-16', 4), '2018-07-20';
+# E Choroba test suite
+is banking-day-offset('2018-06-28', 2, ['2018-07-02', '2018-07-03']), '2018-07-04',
+ 'Land in the middle of holidays';
+is banking-day-offset('2018-06-28', 2, ['2018-07-01', '2018-06-30']), '2018-07-02',
+ 'Holidays on a weekend';
+is banking-day-offset('2024-01-01', 262), '2025-01-01',
+ 'Whole year';
+is banking-day-offset('2018-06-28', 101, [qw[ 2018-11-16 2018-11-19]]), '2018-11-20',
+ 'Holidays wrap a weekend';
+is banking-day-offset('2012-05-22', 161, ['2012-05-22']), '2013-01-03',
+ 'Start on a holiday';
+
+my @h = < 2001-10-08 2005-02-20 2000-01-07 2003-09-26 2000-08-14
+ 2008-09-22 2003-05-10 2004-05-12 2004-10-12 2008-06-12
+ 2003-06-15 2003-09-20 2006-08-01 2009-02-18 2006-07-11
+ 2008-04-01 2003-10-03 2008-08-07 2008-11-17 2009-02-03
+ 2004-08-18 2005-04-23 2003-08-15 2007-03-22 2004-11-07
+ 2004-08-13 2008-09-04 2003-06-27 2006-07-12 2003-11-06
+ 2000-01-30 2006-11-26 2004-07-05 2007-03-07 2000-12-11
+ 2001-01-17 2007-01-18 2002-05-01 2000-01-06 2000-03-03
+ 2005-09-05 2001-01-03 2005-06-02 2003-08-15 2002-09-13
+ 2006-07-15 2005-06-22 2001-10-27 2005-07-14 2004-09-19
+ 2008-02-10 2003-05-10 2007-08-11 2000-02-05 2002-01-25
+ 2002-03-28 2003-07-26 2007-08-13 2002-03-21 2003-03-09
+ 2006-03-11 2004-03-05 2004-05-08 2006-09-24 2000-10-03
+ 2001-12-19 2003-02-26 2005-10-06 2001-08-23 2004-09-25
+ 2009-12-20 2004-10-10 2005-08-15 2001-11-25 2002-03-11
+ 2007-10-22 2000-10-30 2009-04-14 2009-10-30 2004-09-01
+ 2004-04-11 2000-04-04 2003-11-14 2004-11-16 2001-06-28
+ 2008-11-18 2009-11-16 2006-01-27 2007-08-06 2009-09-14
+ 2000-10-25 2001-09-14 2000-09-17 2007-01-07 2005-02-05
+ 2000-09-20 2002-02-01 2003-05-08 2002-06-03 2006-12-02
+ 2009-08-15 2008-11-22 2002-12-23 2002-06-08 2003-09-27
+ 2004-10-08 2007-12-16 2005-12-19 2003-05-15 2007-10-30
+ 2006-11-13 2005-12-04 2006-09-06 2005-05-08 2007-10-23
+ 2006-05-31 2005-01-16 2009-02-15 2000-05-08 2002-04-13
+ 2000-07-11 2005-05-25 2004-07-03 2007-12-03 2008-07-19
+ 2009-08-27 2004-08-27 2002-03-14 2007-03-29 2005-02-03
+ 2004-10-30 2000-07-14 2004-01-27 2004-12-18 2004-12-08
+ 2005-11-23 2008-04-18 2000-03-06 2009-05-31 2002-08-13
+ 2000-12-25 2008-09-17 2004-06-10 2003-04-29 2003-04-28
+ 2000-04-30 2005-04-18 2003-08-01 2000-05-22 2009-03-18
+ 2002-08-08 2008-11-15 2006-03-17 2003-07-17 2006-10-02
+ 2007-01-17 2009-09-04 2000-04-22 2007-04-23 2006-01-08
+ 2003-08-01 2003-08-11 2003-02-10 2007-04-08 2003-02-26
+ 2002-05-16 2002-11-04 2004-01-07 2001-09-28 2001-11-29
+ 2002-03-19 2009-10-08 2002-08-25 2004-08-22 2003-06-23
+ 2001-05-23 2000-12-02 2000-04-26 2000-05-25 2006-05-15
+ 2006-08-18 2009-12-26 2008-07-31 2009-10-02 2002-07-19
+ 2006-08-01 2000-06-09 2006-04-10 >;
+
+is banking-day-offset('2003-04-20', 731, @h), '2006-04-05';
+
sub banking-day-offset($date is copy, $offset is copy, @holidays=[])
{
$date .= Date;
diff --git a/challenge-259/mark-anderson/raku/ch-2.raku b/challenge-259/mark-anderson/raku/ch-2.raku
new file mode 100644
index 0000000000..09272b6c72
--- /dev/null
+++ b/challenge-259/mark-anderson/raku/ch-2.raku
@@ -0,0 +1,29 @@
+#!/usr/bin/env raku
+
+say parse-line('{% id field1="value1" field2="value2" field3=42 %}');
+say parse-line('{% youtube title="Title \"quoted\" done" %}');
+say parse-line('{% youtube title="Title with escaped backslash \\" %}');
+
+grammar Ch2
+{
+ rule TOP { '{%' <ID> <KeyVal>* '%}' }
+ token ID { \w+ }
+ token Key { \w+ }
+ token Quoted { '\"' <[\w\s]>+ '\"' }
+ token Unquoted { <[\w\s]>+ }
+ token Val { '"' [<Quoted> || <Unquoted> || '\\' ]+ '"' || \d+ }
+ rule KeyVal { <Key> '=' <Val> }
+}
+
+sub parse-line($s)
+{
+ my %h;
+ my %fields;
+ my $m = Ch2.parse($s);
+
+ %h<name> = ~$m<ID>;
+ %fields{~.<Key>} = ~.<Val> for $m<KeyVal>;
+ %h<fields> = %fields;
+
+ return %h
+}
diff --git a/challenge-259/peter-campbell-smith/blog.txt b/challenge-259/peter-campbell-smith/blog.txt
new file mode 100644
index 0000000000..c3608ba446
--- /dev/null
+++ b/challenge-259/peter-campbell-smith/blog.txt
@@ -0,0 +1 @@
+http://ccgi.campbellsmiths.force9.co.uk/challenge/259
diff --git a/challenge-259/peter-campbell-smith/perl/ch-1.pl b/challenge-259/peter-campbell-smith/perl/ch-1.pl
new file mode 100755
index 0000000000..2b36c4e28f
--- /dev/null
+++ b/challenge-259/peter-campbell-smith/perl/ch-1.pl
@@ -0,0 +1,159 @@
+#!/usr/bin/perl
+
+# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge
+
+use v5.26; # The Weekly Challenge - 2024-03-04
+use utf8; # Week 259 - task 1 - Banking day offset
+use warnings; # Peter Campbell Smith
+binmode STDOUT, ':utf8';
+
+use Time::Local;
+
+banking_day_offset('2024-03-04', 5);
+banking_day_offset('2024-03-28', 1); # Easter weekend
+banking_day_offset('2024-01-02', 254);
+banking_day_offset('1970-01-01', 10000);
+
+sub banking_day_offset {
+
+ my ($start_date, $unix_date, $one_day, $hol_year, @d,
+ $year, @hols, $hol_string, $ymd_date, $offset);
+
+ ($start_date, $offset) = @_;
+
+ # initialise
+ say qq[\nInput: \$start_date = '$start_date', \$offset = $offset];
+ $start_date =~ m|(....)-(..)-(..)|;
+ $unix_date = timelocal(0, 0, 12, $3, $2 - 1, $1 - 1900);
+
+ $one_day = 86400; # secs in a day
+ $hol_year = 0;
+
+ # move forward day by day
+ while ($offset > 0) {
+ $unix_date += $one_day;
+ @d = localtime($unix_date);
+
+ # weekend no good
+ next if ($d[6] == 0 or $d[6] == 6);
+
+ # bank holiday no good
+ $year = $d[5] + 1900;
+ if ($hol_year != $year) {
+ @hols = bank_hols($year);
+ $hol_string = join('|', @hols);
+ $hol_year = $year;
+ }
+ $ymd_date = sprintf('%04d-%02d-%02d', $year, $d[4] + 1, $d[3]);
+ next if $ymd_date =~ m|$hol_string|;
+
+ # decrement $offset until 0
+ $offset --;
+ }
+
+ say qq[Output: '$ymd_date'];
+}
+
+sub bank_hols { # (year as yyyy)
+
+ # pjcs - 2001-01-29
+
+ my ($year, @hols, $thedate, @d, $x, $dow, $a, $b, $c, $d, $e, $f, $g,
+ $h, $i, $k, $l, $m, $n, $p, $gf);
+
+ # get unix year
+ $year = $_[0] - 1900;
+
+ # New Year = first non-weekend day in year
+ $thedate = timelocal(0, 0, 12, 1, 0, $year);
+ ($x, $x, $x, $x, $x, $x, $dow) = localtime($thedate);
+ $thedate += 86400 if $dow == 0;
+ $thedate += 172800 if $dow == 6;
+ @d = localtime($thedate);
+ push @hols, sprintf('%04d-%02d-%02d', $d[5] + 1900, $d[4] + 1, $d[3]);
+
+ # Good Friday = two days before Easter
+
+# easter algorithm
+
+# Divide by Quotient Remainder
+#
+# the year 19 - a
+# the year 100 b c
+# b 4 d e
+# b + 8 25 f -
+# b - f + 1 3 g -
+# 19*a + b - d - g + 15 30 - h
+# c 4 i k
+# 32 + 2*e + 2*i - h - k 7 - L
+# a + 11*h + 22*L 451 m -
+# h + L - 7*m + 114 31 n p
+#
+# then Easter falls on day p+1 of month n
+
+ ($x, $a) = quorem($year + 1900, 19);
+ ($b, $c) = quorem($year + 1900, 100);
+ ($d, $e) = quorem($b, 4);
+ ($f, $x) = quorem($b + 8, 25);
+ ($g, $x) = quorem($b - $f + 1, 3);
+ ($x, $h) = quorem(19 * $a + $b - $d - $g + 15, 30);
+ ($i, $k) = quorem($c, 4);
+ ($x, $l) = quorem(32 + 2 * $e + 2*$i - $h - $k, 7);
+ ($m, $x) = quorem($a + 11 * $h + 22 * $l, 451);
+ ($n, $p) = quorem($h + $l - 7 * $m + 114, 31);
+
+ $thedate = timelocal(0, 0, 0, $p + 1, $n - 1, $year) - 172800;
+ @d = localtime($thedate);
+ push @hols, sprintf('%04d-%02d-%02d', $d[5] + 1900, $d[4] + 1, $d[3]);
+
+ # Easter Monday = three days after Good Friday
+ $thedate += 3 * 86400;
+ @d = localtime($thedate);
+ push @hols, sprintf('%04d-%02d-%02d', $d[5] + 1900, $d[4] + 1, $d[3]);
+
+ # May Day = first Monday in May
+ $thedate = timelocal(0, 0, 0, 1, 4, $year);
+ ($x, $x, $x, $x, $x, $x, $dow) = localtime($thedate);
+ $dow = -1 if $dow == 6;
+ $thedate += (1 - $dow) * 86400 if $dow <= 0;
+ $thedate += (8 - $dow) * 86400 if $dow >= 2;
+ $thedate += 172800 if $dow == 6;
+ @d = localtime($thedate);
+ push @hols, sprintf('%04d-%02d-%02d', $d[5] + 1900, $d[4] + 1, $d[3]);
+
+ # Spring bank holiday - last Monday in May
+ $thedate = timelocal(0, 0, 0, 1, 5, $year);
+ ($x, $x, $x, $x, $x, $x, $dow) = localtime($thedate);
+ $thedate -= ($dow - 1) * 86400 if $dow >= 2;
+ $thedate -= ($dow + 6) * 86400 if $dow <= 1;
+ @d = localtime($thedate);
+ push @hols, sprintf('%04d-%02d-%02d', $d[5] + 1900, $d[4] + 1, $d[3]);
+
+ # Summer bank holiday - last Monday in August
+ $thedate = timelocal(0, 0, 0, 1, 8, $year);
+ ($x, $x, $x, $x, $x, $x, $dow) = localtime($thedate);
+ $thedate -= ($dow - 1) * 86400 if $dow >= 2;
+ $thedate -= ($dow + 6) * 86400 if $dow <= 1;
+ @d = localtime($thedate);
+ push @hols, sprintf('%04d-%02d-%02d', $d[5] + 1900, $d[4] + 1, $d[3]);
+
+ # Christmas and Boxing Day - 2 weekdays on or after 25 December
+ $thedate = timelocal(0, 0, 12, 24, 11, $year);
+ for $k (0 .. 1) {
+ do {
+ $thedate += 86400;
+ ($x, $x, $x, $x, $x, $x, $dow) = localtime($thedate);
+ } until ($dow >= 1 and $dow <= 5);
+ @d = localtime($thedate);
+ push @hols, sprintf('%04d-%02d-%02d', $d[5] + 1900, $d[4] + 1, $d[3]);
+ }
+
+ return @hols;
+}
+
+sub quorem {
+
+# quorem(a, b) returns (quotient, remainder) of a/b (+ve integers only)
+
+ return (int $_[0]/$_[1], $_[0]%$_[1]);
+}
diff --git a/challenge-259/peter-campbell-smith/perl/ch-2.pl b/challenge-259/peter-campbell-smith/perl/ch-2.pl
new file mode 100755
index 0000000000..3dc077cefb
--- /dev/null
+++ b/challenge-259/peter-campbell-smith/perl/ch-2.pl
@@ -0,0 +1,59 @@
+#!/usr/bin/perl
+
+# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge
+
+use v5.26; # The Weekly Challenge - 2024-03-04
+use utf8; # Week 259 - task 2 - Line parser
+use warnings; # Peter Campbell Smith
+binmode STDOUT, ':utf8';
+
+line_parser('{% id field1="value1" field2="value2" field3=42 %}');
+line_parser('% youtube title="Title \"quoted\" done" %}');
+line_parser('{% youtube title="Title with escaped backslash \\\\" %}');
+
+line_parser('{% id field1="value1" field2="value2" %}
+LINES
+{% endid %}');
+
+sub line_parser {
+
+ my ($input, $id, $output, $field, $value, $first, $rest);
+
+ # initialise
+ $input = shift;
+ say qq[\nInput: ] . $input;
+
+ # detach the 'bonus' part
+ ($input, $rest) = ($1, $2) if $input =~ m|(.*?)\n(.*)|s;
+
+ # encode \x characters as ¬nn¬
+ $input =~ s|\\(.)|'¬' . ord($1) . '¬'|ge;
+
+ # change eg field=22 to field="22"
+ $input =~ s|=(\d+)([ %])|="$1"$2|g;
+
+ # extract id
+ $input =~ m|(\w+)(.*)|;
+ $id = $1;
+ $input = $2;
+ $output = qq[{\n name => $id,\n fields => {\n];
+
+ # extract fields
+ while ($input =~ m|([\w\d]+)\s*=\s*"([\w\d¬ ]+)"|g) {
+ $field = $1;
+ $value = $2;
+
+ # decode ¬nn¬
+ $value =~ s|¬(\d+)¬|chr($1)|ge;
+ $output .= qq[ $field => $value,\n];
+ }
+ $output .= qq[ }\n];
+
+ # extract bonus text
+ if (defined $rest and $rest =~ m|(.*)\{% endid %\}|s) {
+ $output .= qq[ text => $1];
+ }
+ $output .= qq[}\n];
+
+ say qq[Output: $output];
+}
diff --git a/challenge-259/peter-meszaros/perl/ch-1.pl b/challenge-259/peter-meszaros/perl/ch-1.pl
new file mode 100755
index 0000000000..3e16d87eb9
--- /dev/null
+++ b/challenge-259/peter-meszaros/perl/ch-1.pl
@@ -0,0 +1,61 @@
+#!/usr/bin/env perl
+#
+# You are given a start date and offset counter. Optionally you also get bank
+# holiday date list.
+#
+# Given a number (of days) and a start date, return the number (of days)
+# adjusted to take into account non-banking days. In other words: convert a
+# banking day offset to a calendar day offset.
+#
+# Non-banking days are:
+#
+# a) Weekends
+# b) Bank holidays
+#
+# Example 1
+#
+# Input: $start_date = '2018-06-28', $offset = 3, $bank_holidays = ['2018-07-03']
+# Output: '2018-07-04'
+#
+# Thursday bumped to Wednesday (3 day offset, with Monday a bank holiday)
+#
+# Example 2
+#
+# Input: $start_date = '2018-06-28', $offset = 3
+# Output: '2018-07-03'
+#
+
+use strict;
+use warnings;
+use Test2::V0 -no_srand => 1;
+use Data::Dumper;
+use Date::Calc qw/Add_Delta_Days Day_of_Week/;
+
+my $cases = [
+ [ '2018-06-28', 3, ['2018-07-03']],
+ [ '2018-06-28', 3],
+];
+
+sub banking_day_offset
+{
+ my $date = $_[0]->[0];
+ my $offset = $_[0]->[1];
+ my $holidays = $_[0]->[2];
+
+ my %holidays = map { $_, 1 } @$holidays;
+
+ my @date = split(/-/, $date);
+
+ while ($offset > 0) {
+ @date = Add_Delta_Days(@date, 1);
+ my $dow = Day_of_Week(@date);
+ --$offset unless $dow == 6 or $dow == 7 or defined $holidays{sprintf("%04d-%02d-%02d", @date)};
+ }
+ return sprintf("%04d-%02d-%02d", @date);
+}
+
+is(banking_day_offset($cases->[0]), '2018-07-04', 'Example 1');
+is(banking_day_offset($cases->[1]), '2018-07-03', 'Example 2');
+done_testing();
+
+exit 0;
diff --git a/challenge-259/peter-meszaros/perl/ch-2.pl b/challenge-259/peter-meszaros/perl/ch-2.pl
new file mode 100755
index 0000000000..190476a03a
--- /dev/null
+++ b/challenge-259/peter-meszaros/perl/ch-2.pl
@@ -0,0 +1,99 @@
+#!/usr/bin/env perl
+#
+# You are given a line like below:
+#
+# {% id field1="value1" field2="value2" field3=42 %}
+#
+# Where
+#
+# a) "id" can be \w+.
+# b) There can be 0 or more field-value pairs.
+# c) The name of the fields are \w+.
+# b) The values are either number in which case we don't need double quotes or
+# string in which case we need double quotes around them.
+#
+# The line parser should return structure like below:
+# {
+# name => id,
+# fields => {
+# field1 => value1,
+# field2 => value2,
+# field3 => value3,
+# }
+# }
+#
+# It should be able to parse the following edge cases too:
+# {% youtube title="Title \"quoted\" done" %}
+# and
+# {% youtube title="Title with escaped backslash \\" %}
+#
+# BONUS: Extend it to be able to handle multiline tags:
+#
+# {% id filed1="value1" ... %}
+# LINES
+# {% endid %}
+#
+# You should expect the following structure from your line parser:
+# {
+# name => id,
+# fields => {
+# field1 => value1,
+# field2 => value2,
+# field3 => value3,
+# }
+# text => LINES
+# }
+#
+
+use strict;
+use warnings;
+use Test2::V0 -no_srand => 1;
+use Data::Dumper;
+
+my $cases = [
+ q/{% id field1="value1" field2="value2" field3=42 %}/,
+ q/{% id field1="value1" field2="va \"xxx\" lue2" field3=42 %}/,
+ q/{% %}/,
+];
+
+sub line_parser
+{
+ my $row = shift;
+
+ my $href = {};
+
+ $row =~ /\{%\s*(\w+)/;
+ return undef unless $1;
+
+ $href->{name} = $1;
+
+ $row =~ s/\\"/\034/g;
+ while ($row =~ /([\w\d]+)="?(\d+|[\w\034\s]+)"?/cg) {
+ my $f = $1;
+ my $v = $2;
+ $v =~ s/\034/"/g;
+ $href->{fields}->{$f} = $v;
+ }
+
+ return $href;
+}
+
+is(line_parser($cases->[0]), { name => 'id',
+ fields => {
+ field1 => 'value1',
+ field2 => 'value2',
+ field3 => 42,
+ }
+ }, 'Example 1');
+is(line_parser($cases->[1]), { name => 'id',
+ fields => {
+ field1 => 'value1',
+ field2 => 'va "xxx" lue2',
+ field3 => 42,
+ }
+ }, 'Example 2');
+is(line_parser($cases->[2]), undef, 'Example 3');
+done_testing();
+
+exit 0;
+
diff --git a/challenge-259/roger-bell-west/javascript/ch-1.js b/challenge-259/roger-bell-west/javascript/ch-1.js
new file mode 100755
index 0000000000..903fd4e349
--- /dev/null
+++ b/challenge-259/roger-bell-west/javascript/ch-1.js
@@ -0,0 +1,30 @@
+#! /usr/bin/node
+
+"use strict"
+
+function bankingdayoffset(start, offset, bankholidays) {
+ let bh = new Set(bankholidays.map(x => new Date(Date.parse(x)).toString()));
+ let d = new Date(Date.parse(start));
+ for (let i = 1; i <= offset; i++) {
+ d.setDate(d.getDate() + 1);
+ while (bh.has(d.toString()) || d.getDay() == 0 || d.getDay() == 6) {
+ d.setDate(d.getDate() + 1);
+ }
+ }
+ return d.getFullYear().toString().padStart(4, "0") + "-" +
+ (d.getMonth()+1).toString().padStart(2, "0") + "-" +
+ d.getDate().toString().padStart(2, "0");
+}
+
+if (bankingdayoffset('2018-06-28', 3, ['2018-07-03']) == '2018-07-04') {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write(" ");
+if (bankingdayoffset('2018-06-28', 3, []) == '2018-07-03') {
+ process.stdout.write("Pass");
+} else {
+ process.stdout.write("FAIL");
+}
+process.stdout.write("\n");
diff --git a/challenge-259/roger-bell-west/kotlin/ch-1.kt b/challenge-259/roger-bell-west/kotlin/ch-1.kt
new file mode 100644
index 0000000000..9b7cfb52aa
--- /dev/null
+++ b/challenge-259/roger-bell-west/kotlin/ch-1.kt
@@ -0,0 +1,32 @@
+import java.time.LocalDate
+import java.time.format.DateTimeFormatter
+
+fun bankingdayoffset(start: String, offset: Int, bankholidays: List<String>): String {
+ val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
+ val bh = bankholidays.map {LocalDate.parse(it, formatter)}.toSet()
+ var current = LocalDate.parse(start, formatter)
+ for (i in 1 .. offset) {
+ current = current.plusDays(1)
+ while (bh.contains(current) || current.getDayOfWeek().getValue() > 5) {
+ current = current.plusDays(1)
+ }
+ }
+ return current.format(formatter)
+}
+
+fun main() {
+
+ if (bankingdayoffset("2018-06-28", 3, listOf("2018-07-03")) == "2018-07-04") {
+ print("Pass")
+ } else {
+ print("Fail")
+ }
+ print(" ")
+ if (bankingdayoffset("2018-06-28", 3, emptyList<String>()) == "2018-07-03") {
+ print("Pass")