diff options
| -rwxr-xr-x | challenge-103/jo-37/perl/ch-1.pl | 110 | ||||
| -rwxr-xr-x | challenge-103/jo-37/perl/ch-1a.pl | 27 | ||||
| -rw-r--r-- | challenge-103/jo-37/perl/ch-2.csv | 7 | ||||
| -rwxr-xr-x | challenge-103/jo-37/perl/ch-2.pl | 122 |
4 files changed, 266 insertions, 0 deletions
diff --git a/challenge-103/jo-37/perl/ch-1.pl b/challenge-103/jo-37/perl/ch-1.pl new file mode 100755 index 0000000000..40aac35b88 --- /dev/null +++ b/challenge-103/jo-37/perl/ch-1.pl @@ -0,0 +1,110 @@ +#!/usr/bin/perl -s + +use v5.16; +use Test2::V0; +use List::Util 'pairmap'; +use List::MoreUtils 'natatime'; +use experimental qw(signatures postderef); + +our ($tests, $examples); + +run_tests() if $tests || $examples; # does not return + +die <<EOS unless @ARGV; +usage: $0 [-examples] [-tests] [year] + +-examples + run the examples from the challenge + +-tests + run some tests + +year + print element and animal for most time of <year> + +EOS + + +### Input and Output + +say "@{[ch_zod(shift)]}"; + + +### Implementation + +{ + my (@cz, @l); + + BEGIN { + @cz = map [map [unpack '(A2)*'], unpack '(A2/A*)*'], unpack '(A4/A*)*', + '00080632658900561012041900111022001904170822141403080508170410' . + '04001719070134121214131004241417141418190417060314060615080606' . + '17001904142310190806041712170001010819120317000614131018130010' . + '041007141718040806140019'; + @l = sub {map chr($_[0] + $_), $_[1] .. $_[2]}->($cz[0][0]->@*); + } + + sub ch_zod ($y) { + local $" = ''; + + pairmap {"\u@l[$cz[$a][$b]->@*]"} 1, ($y % 10)/2, 2, $y % 12; + } +} + +### Examples and tests + +sub run_tests { + SKIP: { + skip "examples" unless $examples; + + is [ch_zod(2017)], [qw(Fire Rooster)], 'example 1'; + is [ch_zod(1938)], [qw(Earth Tiger)], 'example 2'; + } + + SKIP: { + skip "tests" unless $tests; + + # all elements and animals: + my $three = natatime 3, + 1924, 'Wood', 'Rat', + 1925, 'Wood', 'Ox', + 1926, 'Fire', 'Tiger', + 1927, 'Fire', 'Rabbit', + 1928, 'Earth', 'Dragon', + 1929, 'Earth', 'Snake', + 1930, 'Metal', 'Horse', + 1931, 'Metal', 'Goat', + 1932, 'Water', 'Monkey', + 1933, 'Water', 'Rooster', + 1934, 'Wood', 'Dog', + 1935, 'Wood', 'Pig'; + while (my @t = $three->()) { + is [ch_zod($t[0])], [$t[1], $t[2]], "$t[0]: $t[1] $t[2]"; + } + } + + done_testing; + exit; +} + +__DATA__ + +"The string" consists of three parts of the form llllxxxx... with llll +as the part's length and xxxx as the content. Each part has the form +llyyyy... with ll as the length and yyyy as the content for a variable +number of sub parts. Finally each sub part is split into 2-digit +decimal numbers. +* Part #0 has one sub part containing the decimal ASCII code for ' ' and + the offsets of 'a' and 'y' from ' ', thus keeping all of them at two + digits. +* Part #1 has five sub parts containing the offsets of the elements' + characters from 'a'. +* Part #2 has twelve sub parts containing the offsets of the animals' + characters from 'a'. +Part #1 and #2 can be generated by ch-1a.pl. A three-dimensional array +@cz is build from these parts where the first index selects +alphabet/element/animal and the second index the item within this +category. The letters of the alphabet are gathered in the array @l. + +The "chinese zodiac" sub assembles the year's element and animal as +title cased array slices from the letters. diff --git a/challenge-103/jo-37/perl/ch-1a.pl b/challenge-103/jo-37/perl/ch-1a.pl new file mode 100755 index 0000000000..8a6a5334a3 --- /dev/null +++ b/challenge-103/jo-37/perl/ch-1a.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl + +use v5.16; +use warnings; + +die <<EOS unless @ARGV; +usage: $0 word ... + +word ... + words to encode + +EOS + +# ./ch-1a.pl metal water wood fire earth +# ./ch-1a.pl monkey rooster dog pig rat ox tiger rabbit dragon snake horse goat + +use constant A => ord('a'); + +my $buf; +for (@ARGV) { + my $wbuf; + for (split //) { + $wbuf .= sprintf "%02d", ord() - A; + } + $buf .= sprintf "%02d%s", 2 * length, $wbuf; +} +printf "%04d%s\n", length($buf), $buf; diff --git a/challenge-103/jo-37/perl/ch-2.csv b/challenge-103/jo-37/perl/ch-2.csv new file mode 100644 index 0000000000..9428b93004 --- /dev/null +++ b/challenge-103/jo-37/perl/ch-2.csv @@ -0,0 +1,7 @@ +1709363,"Les Miserables Episode 1: The Bishop (broadcast date: 1937-07-23)" +1723781,"Les Miserables Episode 2: Javert (broadcast date: 1937-07-30)" +1723781,"Les Miserables Episode 3: The Trial (broadcast date: 1937-08-06)" +1678356,"Les Miserables Episode 4: Cosette (broadcast date: 1937-08-13)" +1646043,"Les Miserables Episode 5: The Grave (broadcast date: 1937-08-20)" +1714640,"Les Miserables Episode 6: The Barricade (broadcast date: 1937-08-27)" +1714640,"Les Miserables Episode 7: Conclusion (broadcast date: 1937-09-03)" diff --git a/challenge-103/jo-37/perl/ch-2.pl b/challenge-103/jo-37/perl/ch-2.pl new file mode 100755 index 0000000000..82e79962f3 --- /dev/null +++ b/challenge-103/jo-37/perl/ch-2.pl @@ -0,0 +1,122 @@ +#!/usr/bin/perl -s + +use v5.16; +use Mojo::CSV; +use DateTime::Format::Duration; +use Test2::V0; +use Test2::API qw(test2_add_callback_context_init); +use experimental 'signatures'; + +our ($tests, $examples); + + +run_tests() if $tests || $examples; # does not return + +die <<EOS unless @ARGV == 3; +usage: $0 [-examples] [-tests] [start now playlist] + +-examples + run the examples from the challenge + +-tests + run some tests + +start + starttime of streamer + +now + "current" time + +playlist + filename of playlist, must be in CSV format + +call "$0 1606134123 1614591276 ch-2.csv" for the task's example. + +EOS + + +### Input and Output + +my ($start, $now, $csv) = @ARGV; +say for playing_now($start, $now, $csv); + + +### Implementation + +# Normalizing formatter for a DateTime::Duration object. +use constant DT_D_FMT => DateTime::Format::Duration->new( + pattern => '%r', normalize => 1); + +# Find the currently running track from the playlist and the running +# time within this track given the mediaplayer start, a current time and +# a csv file containing the playlist. +sub playing_now ($start, $now, $file) { + # Read the playlist from a CSV file or file handle. + # Presume two fields: track duration in ms and track title. + my $playlist = Mojo::CSV->new->slurp($file); + + # Calculate the total running time of the playlist and append the + # individual start and end time offsets to each track along the way. + my $total = $playlist->reduce( + sub { + $b->[2] = $a; # start + $b->[3] = $a + $b->[0]; # end + }, 0); + + # Calculate the time from the recent playlist start till now (in + # milliseconds). + my $listtime = ($now - $start) * 1000 % $total; + + # Find the currently running track. + my $current = $playlist->first(sub {$_->[3] > $listtime}); + + # Return the current track's title and running time. + ($current->[1], + DT_D_FMT->format_duration_from_deltas( + seconds => ($listtime - $current->[2]) / 1000)); +} + + +### Examples and tests + +sub run_tests { + + my $fh = *DATA{IO}; + my $head = tell $fh; + test2_add_callback_context_init(sub {seek $fh, $head, 0}); + + SKIP: { + skip "examples" unless $examples; + + like [playing_now(1606134123, 1614591276, $fh)], + [qr/Episode 1/, '00:10:24'], 'example'; + } + + SKIP: { + skip "tests" unless $tests; + + like [playing_now(1606134123, 1614590652, $fh)], + [qr/Episode 1/, '00:00:00'], 'start of episode 1'; + + like [playing_now(1606134123, 1606135832, $fh)], + [qr/Episode 1/, '00:28:29'], 'end of episode 1'; + + like [playing_now(1606134123, 1606135833, $fh)], + [qr/Episode 2/, '00:00:00'], 'start of episode 2'; + + like [playing_now(1606134123, 1606144319, $fh)], + [qr/Episode 7/, '00:00:00'], 'start of episode 7'; + } + + done_testing; + exit; +} + +__DATA__ +1709363,"Les Miserables Episode 1: The Bishop (broadcast date: 1937-07-23)" +1723781,"Les Miserables Episode 2: Javert (broadcast date: 1937-07-30)" +1723781,"Les Miserables Episode 3: The Trial (broadcast date: 1937-08-06)" +1678356,"Les Miserables Episode 4: Cosette (broadcast date: 1937-08-13)" +1646043,"Les Miserables Episode 5: The Grave (broadcast date: 1937-08-20)" +1714640,"Les Miserables Episode 6: The Barricade (broadcast date: 1937-08-27)" +1714640,"Les Miserables Episode 7: Conclusion (broadcast date: 1937-09-03)" |
