diff options
Diffstat (limited to 'challenge-259')
| -rw-r--r-- | challenge-259/wlmb/blog.txt | 1 | ||||
| -rwxr-xr-x | challenge-259/wlmb/perl/ch-1.pl | 40 | ||||
| -rwxr-xr-x | challenge-259/wlmb/perl/ch-2.pl | 40 |
3 files changed, 81 insertions, 0 deletions
diff --git a/challenge-259/wlmb/blog.txt b/challenge-259/wlmb/blog.txt new file mode 100644 index 0000000000..78da93642d --- /dev/null +++ b/challenge-259/wlmb/blog.txt @@ -0,0 +1 @@ +https://wlmb.github.io/2024/03/04/PWC259/ diff --git a/challenge-259/wlmb/perl/ch-1.pl b/challenge-259/wlmb/perl/ch-1.pl new file mode 100755 index 0000000000..66be0993b7 --- /dev/null +++ b/challenge-259/wlmb/perl/ch-1.pl @@ -0,0 +1,40 @@ +#!/usr/bin/env perl +# Perl weekly challenge 259 +# Task 1: Banking Day Offset +# +# See https://wlmb.github.io/2024/03/04/PWC259/#task-1-banking-day-offset +use v5.36; +use DateTime; +use DateTime::Format::DateParse qw(parse_datetime); +use List::AllUtils qw(uniq_by); +use POSIX qw(floor); +die <<~"FIN" unless @ARGV >= 2; + Usage ch-1.pl S D [B1 B2...] + to bump daye S by D days skipping weekends and + the (optional) bank holidays B1 B2... + FIN +my ($start_str, $offset, @bank_str)=@ARGV; +my ($start, @bank)= # convert to dates + map + {DateTime::Format::DateParse->parse_datetime($_)->truncate(to=>'day')} + ($start_str, @bank_str); +my $fullweeks=floor($offset/5); +my $remaining=$offset%5; +my $end=$start->clone; +my $weekday=$end->day_of_week; +$end->add(days=>8-$weekday), $weekday=1 if $weekday>5; +$end->add(days=>7*$fullweeks+$remaining); +skip_weekend($end); +bank_adjust($_,$start,$end) for + sort {DateTime->compare($a, $b)} uniq_by {"".$_} @bank; # remove duplicate dates and sort +say "Start: $start_str. Offset $offset. Holidays: @bank_str -> ", $end->ymd; +sub skip_weekend($date){ + my $weekday=$date->day_of_week; + $date->add(days=>2) if $weekday>5; +} +sub bank_adjust($date, $start, $end){ + return if $date->day_of_week >5 || + DateTime->compare($date, $start) < 0 || DateTime->compare($date, $end) > 0; + $end->add(days=>1); + $end->add(days=>2) if $end->day_of_week>5; # skip weekend +} diff --git a/challenge-259/wlmb/perl/ch-2.pl b/challenge-259/wlmb/perl/ch-2.pl new file mode 100755 index 0000000000..e37f23333b --- /dev/null +++ b/challenge-259/wlmb/perl/ch-2.pl @@ -0,0 +1,40 @@ +#!/usr/bin/env perl +# Perl weekly challenge 259 +# Task 2: Line Parser +# +# See https://wlmb.github.io/2024/03/04/PWC259/#task-2-line-parser +use v5.36; +use Parse::RecDescent; +use Data::Dumper; +local $/; +my $input=<>; +our @result; +my $grammar=q{ + {my $id;} + startrule: record(s) eof + { $return = $item[1] } + record: single lines + { $return = { + %{$item[1]}, + text => join " ", $item[2]->@* } + } + | single + single: '{%' id keyval(s) '%}' + { $return = { name => $item[2], fields => { map {%$_} $item[3]->@*} }; } + id: /\w+/ + { $id=$item[1]; } + lines: line(s) '{%' "end" "$id" '%}' + { $return = $item[1]; } + line: /.*/ + { $return=$item[1]; $item[1]=~/^\{%/?undef:1; } + keyval: key "=" val + { $return = {$item[1]=>$item[3]} } + key: /\w+/ + val: number | string + number: /\d+/ + string: /"(?:[^"\n]|\\")*"/ + eof: /^\Z/ +}; +my $parser=Parse::RecDescent->new($grammar); +my $parse=$parser->startrule($input); +say Dumper($parse); |
