diff options
| -rw-r--r-- | challenge-259/packy-anderson/README.md | 2 | ||||
| -rw-r--r-- | challenge-259/packy-anderson/blog.txt | 1 | ||||
| -rw-r--r-- | challenge-259/packy-anderson/data/parser-1.txt | 1 | ||||
| -rw-r--r-- | challenge-259/packy-anderson/data/parser-2.txt | 1 | ||||
| -rw-r--r-- | challenge-259/packy-anderson/data/parser-3.txt | 1 | ||||
| -rw-r--r-- | challenge-259/packy-anderson/data/parser-4.txt | 3 | ||||
| -rw-r--r-- | challenge-259/packy-anderson/data/parser-5.txt | 15 | ||||
| -rwxr-xr-x | challenge-259/packy-anderson/perl/ch-1.pl | 65 | ||||
| -rwxr-xr-x | challenge-259/packy-anderson/python/ch-1.py | 56 | ||||
| -rwxr-xr-x | challenge-259/packy-anderson/raku/ch-1.raku | 62 | ||||
| -rwxr-xr-x | challenge-259/packy-anderson/raku/ch-2.raku | 89 |
11 files changed, 295 insertions, 1 deletions
diff --git a/challenge-259/packy-anderson/README.md b/challenge-259/packy-anderson/README.md index 64879ee70c..fb3836f0bb 100644 --- a/challenge-259/packy-anderson/README.md +++ b/challenge-259/packy-anderson/README.md @@ -16,4 +16,4 @@ ## Blog Post -[Even Digits have a Sum!](https://packy.dardan.com/b/J8) +[Ba-a-nking Day! Ba-a-nking Day! That's all I really wanted to say...](https://packy.dardan.com/b/JC) diff --git a/challenge-259/packy-anderson/blog.txt b/challenge-259/packy-anderson/blog.txt new file mode 100644 index 0000000000..5b67e28b89 --- /dev/null +++ b/challenge-259/packy-anderson/blog.txt @@ -0,0 +1 @@ +https://packy.dardan.com/b/JC
\ No newline at end of file diff --git a/challenge-259/packy-anderson/data/parser-1.txt b/challenge-259/packy-anderson/data/parser-1.txt new file mode 100644 index 0000000000..9fb85876cd --- /dev/null +++ b/challenge-259/packy-anderson/data/parser-1.txt @@ -0,0 +1 @@ +{% id field1="value1" field2="value2" field3=42 %}
\ No newline at end of file diff --git a/challenge-259/packy-anderson/data/parser-2.txt b/challenge-259/packy-anderson/data/parser-2.txt new file mode 100644 index 0000000000..67eaf60282 --- /dev/null +++ b/challenge-259/packy-anderson/data/parser-2.txt @@ -0,0 +1 @@ +{% youtube title="Title \"quoted\" done" %}
\ No newline at end of file diff --git a/challenge-259/packy-anderson/data/parser-3.txt b/challenge-259/packy-anderson/data/parser-3.txt new file mode 100644 index 0000000000..e7448b0bc3 --- /dev/null +++ b/challenge-259/packy-anderson/data/parser-3.txt @@ -0,0 +1 @@ +{% youtube title="Title with escaped backslash \\" %}
\ No newline at end of file diff --git a/challenge-259/packy-anderson/data/parser-4.txt b/challenge-259/packy-anderson/data/parser-4.txt new file mode 100644 index 0000000000..957c351f1a --- /dev/null +++ b/challenge-259/packy-anderson/data/parser-4.txt @@ -0,0 +1,3 @@ +{% id filed1="value1" %} +LINES +{% endid %} diff --git a/challenge-259/packy-anderson/data/parser-5.txt b/challenge-259/packy-anderson/data/parser-5.txt new file mode 100644 index 0000000000..378ecf6099 --- /dev/null +++ b/challenge-259/packy-anderson/data/parser-5.txt @@ -0,0 +1,15 @@ +JUNK +{% id filed1="value1" %} +LINES +LINES +LINES +{% endid %} + +{% foo foonum=3 %} +FOO +BAR +BAZ +{% endfoo %} +JUNK +JUNK +JUNK diff --git a/challenge-259/packy-anderson/perl/ch-1.pl b/challenge-259/packy-anderson/perl/ch-1.pl new file mode 100755 index 0000000000..b1389d9d65 --- /dev/null +++ b/challenge-259/packy-anderson/perl/ch-1.pl @@ -0,0 +1,65 @@ +#!/usr/bin/env perl +use v5.38; + +use List::Util qw( any ); +use Time::Piece; +use Time::Seconds qw( ONE_DAY ); + +sub bankingDayOffset($start, $offset, @holidays) { + # convert string to Date + my $date = Time::Piece->strptime($start, "%Y-%m-%d") + ->truncate(to => 'day'); + my $cnt = 0; + + # convert holidays to Date objects + @holidays = map { + Time::Piece->strptime($_, "%Y-%m-%d") + ->truncate(to => 'day') + } @holidays; + + my @explain; + my $this_day = $date->fullday; + while ($offset) { + $date += ONE_DAY; # add 1 day + my $next_day = $date->fullday; + if ( + $date->wday == 7 || # it's a Saturday + $date->wday == 1 # it's a Sunday + ) { + push @explain, + "$next_day skipped because it's a weekend"; + } + elsif (any { $date == $_ } @holidays) { # it's a Holiday + push @explain, + "$next_day skipped because it's a holiday"; + } + else { + $offset--; $cnt++; + push @explain, + "$this_day bumped to $next_day (offset $cnt)"; + $this_day = $next_day; + } + } + return $date->strftime('%F'), join("\n", @explain); +} + +sub solution($start, $offset, @holidays) { + my $holiday_display = ''; + if (@holidays) { + $holiday_display = qq{,\n \$bank_holidays = ['} + . join(q{', '}, @holidays) . q{']}; + } + say qq{Input: \$start_date = '$start', \$offset = $offset$holiday_display}; + my ($output, $explain) = bankingDayOffset($start, $offset, @holidays); + say qq{Output: '$output'}; + say qq{\n$explain}; +} + +say "Example 1:"; +solution('2018-06-28', 3, '2018-07-03'); + +say "\nExample 2:"; +solution('2018-06-28', 3); + +say "\nExample 3:"; +solution('2023-12-29', 5, '2024-01-01');
\ No newline at end of file diff --git a/challenge-259/packy-anderson/python/ch-1.py b/challenge-259/packy-anderson/python/ch-1.py new file mode 100755 index 0000000000..fc608d9033 --- /dev/null +++ b/challenge-259/packy-anderson/python/ch-1.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +from datetime import date, timedelta + +def bankingDayOffset(start, offset, holidays): + d = date.fromisoformat(start) # convert string to Date + cnt = 0 + + # convert holidays to Date objects + holidays = [ date.fromisoformat(h) for h in holidays ] + + explain = [] + this_day = d.strftime('%A') + while offset: + d += timedelta(days = 1) # add 1 day + next_day = d.strftime('%A') + if ( + d.isoweekday() == 6 or # it's a Saturday + d.isoweekday() == 7 # it's a Sunday + ): + explain.append( + f"{next_day} skipped because it's a weekend" + ) + elif any([d == h for h in holidays]): # it's a Holiday + explain.append( + f"{next_day} skipped because it's a holiday" + ) + else: + offset -= 1 + cnt += 1 + explain.append( + f"{next_day} bumped to {next_day} (offset {cnt})" + ) + this_day = next_day + return d.strftime('%F'), "\n".join(explain) + +def solution(start, offset, holidays): + holiday_display = '' + if holidays: + holiday_display = ( + "\n $bank_holidays = ['" + + "', '".join(holidays) + "']" + ) + print(f"Input: $start_date = '{start}', $offset = {offset}{holiday_display}") + output, explain = bankingDayOffset(start, offset, holidays) + print(f"Output: '{output}'") + print(f"\n{explain}") + +print('Example 1:') +solution('2018-06-28', 3, ['2018-07-03']) + +print('\nExample 2:') +solution('2018-06-28', 3, []) + +print('\nExample 3:') +solution('2023-12-29', 5, ['2024-01-01']) diff --git a/challenge-259/packy-anderson/raku/ch-1.raku b/challenge-259/packy-anderson/raku/ch-1.raku new file mode 100755 index 0000000000..d8eb834a31 --- /dev/null +++ b/challenge-259/packy-anderson/raku/ch-1.raku @@ -0,0 +1,62 @@ +#!/usr/bin/env raku +use v6; + +use Date::Names; + +sub bankingDayOffset($start, $offset, @holidays) { + my $date = Date.new($start); # convert string to Date + my $off = $offset; + my $cnt = 0; + + # convert holidays to Date objects + @holidays = map { Date.new($_) }, @holidays; + + # instantiate a Date::Names object + my $dn = Date::Names.new; + + my @explain; + my $this_day = $dn.dow($date.day-of-week); + while ($off) { + $date++; + my $next_day = $dn.dow($date.day-of-week); + if ( + $date.day-of-week == 6 || # it's a Saturday + $date.day-of-week == 7 # it's a Sunday + ) { + @explain.push: + "$next_day skipped because it's a weekend"; + } + elsif ($date == @holidays.any) { # it's a Holiday + @explain.push: + "$next_day skipped because it's a holiday"; + } + else { + $off--; $cnt++; + @explain.push: + "$this_day bumped to $next_day (offset $cnt)"; + $this_day = $next_day; + } + } + return $date.gist, @explain.join("\n"); +} + +sub solution($start, $offset, @holidays) { + my $holiday_display = ''; + if (@holidays) { + $holiday_display = qq{,\n \$bank_holidays = ['} + ~ @holidays.join(q{', '}) ~ q{']}; + } + say qq{Input: \$start_date = '$start', \$offset = $offset$holiday_display}; + my ($output, $explain) = bankingDayOffset($start, $offset, @holidays); + say qq{Output: '$output'}; + say qq{\n$explain}; +} + +say "Example 1:"; +solution('2018-06-28', 3, ['2018-07-03']); + +say "\nExample 2:"; +solution('2018-06-28', 3, []); + +say "\nExample 3:"; +solution('2023-12-29', 5, ['2024-01-01']);
\ No newline at end of file diff --git a/challenge-259/packy-anderson/raku/ch-2.raku b/challenge-259/packy-anderson/raku/ch-2.raku new file mode 100755 index 0000000000..04894b08f9 --- /dev/null +++ b/challenge-259/packy-anderson/raku/ch-2.raku @@ -0,0 +1,89 @@ +#!/usr/bin/env raku +use v6; + +grammar Parser { + rule TOP { [ <line> | <text> ] } + + rule line { '{%' <id> [ <field-value> ]* '%}' } + + # negative lookbehind and negative lookahead + rule text { <!after 「{%」 > <-[ \n ]>+ <!before 「%}」 >} + + token id { \w+ } + token field { \w+ } + + token number { \d+ [ \. \d+ ]? } + + token quoted-string { '"' <string> '"' } + token string { + [ + <-[ " ]> # any character not a quote + | + 「\\」 # an escaped backslash + | + \\\" # an escaped quote + ]* + } + + rule field-value { <field> '=' [<number> | <quoted-string>] } +} + +sub MAIN($file) { + my %data; + my @ids; + my $in_id = ''; + for $file.IO.lines -> $line { + # parse this line of the file + my $p = Parser.parse($line); + + # is there a line with {% ... %} ? + if ($p<line>) { + my $id = $p<line><id>.Str; + # is the id the end of a block? + if (my $c = ($id ~~ / end(\w+) /)) { # capture after end + if (%data{$c[0]}:exists) { # it is! + $id = $c[0]; + $in_id = ''; # clear the id we're processing + if (%data{$id}{'text'}) { + # if there's text, remove the final "newline" + %data{$id}{'text'} ~~ s/\\n$//; + } + next; # skip to next line of file + } + } + @ids.push($id); # keep list of ids in order + $in_id = $id; # keep track of the current id for text + # initialize base data for this id + %data{$id} = { name => $id }; + # if we have fields... + if ($p<line><field-value>) { + # loop over them and store them in the data + for $p<line><field-value> -> $fv { + my $field = $fv<field>; + my $value = $fv<number> ?? $fv<number> + !! $fv<quoted-string><string>; + %data{$id}{'fields'}{$field} = $value; + } + } + } + # if we have non-{% ... %} lines and we have an ID + elsif ($p<text> && $in_id) { + # append a "newline" to the end + %data{$in_id}{'text'} ~= $p<text> ~ "\\n"; + } + } + + # dump the data + for @ids -> $id { + my %group = %data{$id}; + say "\{"; + say " name => %group{'name'},"; + say " fields => \{"; + for %group{'fields'}.keys.sort -> $k { + say " $k => %group{'fields'}{$k},"; + } + say " }"; + say " text => %group{'text'}" if %group{'text'}; + say "\}"; + } +} |
