diff options
| author | Jörg Sommrey <28217714+jo-37@users.noreply.github.com> | 2023-03-29 17:40:50 +0200 |
|---|---|---|
| committer | Jörg Sommrey <28217714+jo-37@users.noreply.github.com> | 2023-04-19 17:15:36 +0200 |
| commit | 16aea00999acf68f2adaaa40c35d7b6b0b531b86 (patch) | |
| tree | 46ac8a111041fea6abdb918e09e42d7804390a4f /challenge-039 | |
| parent | ec262302b6392eae88df06834c81f54d725e2205 (diff) | |
| download | perlweeklychallenge-club-16aea00999acf68f2adaaa40c35d7b6b0b531b86.tar.gz perlweeklychallenge-club-16aea00999acf68f2adaaa40c35d7b6b0b531b86.tar.bz2 perlweeklychallenge-club-16aea00999acf68f2adaaa40c35d7b6b0b531b86.zip | |
Challenge 039 task 1
Diffstat (limited to 'challenge-039')
| -rwxr-xr-x | challenge-039/jo-37/perl/ch-1.pl | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/challenge-039/jo-37/perl/ch-1.pl b/challenge-039/jo-37/perl/ch-1.pl new file mode 100755 index 0000000000..5b28a33207 --- /dev/null +++ b/challenge-039/jo-37/perl/ch-1.pl @@ -0,0 +1,102 @@ +#!/usr/bin/perl -s + +use v5.16; +use Test2::V0; +use DateTime::Duration; +use DateTime::Format::Strptime; +use List::UtilsBy 'sort_by'; +use experimental 'signatures'; + +our ($tests, $examples); + +run_tests() if $tests || $examples; # does not return + +die <<EOS unless @ARGV; +usage: $0 [-examples] [-tests] [GUESTBOOK] + +-examples + run the examples from the challenge + +-tests + run some tests + +GUESTBOOK + name of guestbook file. Use '-' for STDIN. + +EOS + + +### Input and Output + +say light_duration(\*ARGV)->in_units('minutes'); + + +### Implementation + +# Converting the guestbook into a list of events. Each event consists +# of a time and the change in number of guests, i.e. the IN-time with an +# increment of one and the OUT-time with a decrement of one. Processing +# the events in timed order reveals the number of guests before and +# after each event. When coming from zero, the switch-on time is +# recorded and when going to zero the swich-on duration is cumulated. + +sub light_duration ($fh) { + my @events; + my $parser = DateTime::Format::Strptime->new(pattern => '%H:%M'); + # Convert guestbook entries to events. + while (<$fh>) { + /^.*?\s+IN:\s*(\d{2}:\d{2})\s+OUT:\s*(\d{2}:\d{2})$/i or next; + push @events, [$parser->parse_datetime($1), 1], + [$parser->parse_datetime($2), -1]; + } + my $light_dur = DateTime::Duration->new; + my $guests = 0; + my $starttime; + # Process events in timed order. + for my $event (sort_by {$_->[0]} @events) { + $starttime = $event->[0] unless $guests; + $guests += $event->[1]; + $light_dur += $event->[0] - $starttime unless $guests; + } + + $light_dur; +} + + +### Examples and tests + +sub run_tests { + SKIP: { + skip "examples" unless $examples; + + my $guestbook = <<EOS; +1) Alex IN: 09:10 OUT: 09:45 +2) Arnold IN: 09:15 OUT: 09:33 +3) Bob IN: 09:22 OUT: 09:55 +4) Charlie IN: 09:25 OUT: 10:05 +5) Steve IN: 09:33 OUT: 10:01 +6) Roger IN: 09:44 OUT: 10:12 +7) David IN: 09:57 OUT: 10:23 +8) Neil IN: 10:01 OUT: 10:19 +9) Chris IN: 10:10 OUT: 11:00 +EOS + open my $fh, '<', \$guestbook; + is light_duration($fh)->in_units('minutes'), 110, 'task 1'; + } + + SKIP: { + skip "tests" unless $tests; + + my $guestbook = <<EOS; +1) A IN: 09:00 OUT: 10:00 +2) B IN: 09:30 OUT: 10:30 +3) C IN: 11:00 OUT: 12:00 +4) D IN: 11:30 OUT: 12:30 +EOS + open my $fh, '<', \$guestbook; + is light_duration($fh)->in_units('minutes'), 180, 'two segments'; + } + + done_testing; + exit; +} |
