From ae648e8c3b856cff336cd9defa31e6ad2dfaa767 Mon Sep 17 00:00:00 2001 From: drbaggy Date: Mon, 17 Oct 2022 07:34:43 +0100 Subject: challenge 187 --- challenge-187/james-smith/README.md | 302 +++++---------------------------- challenge-187/james-smith/blog.txt | 1 + challenge-187/james-smith/perl/ch-1.pl | 31 ++++ challenge-187/james-smith/perl/ch-2.pl | 36 ++++ 4 files changed, 114 insertions(+), 256 deletions(-) create mode 100644 challenge-187/james-smith/blog.txt create mode 100644 challenge-187/james-smith/perl/ch-1.pl create mode 100644 challenge-187/james-smith/perl/ch-2.pl diff --git a/challenge-187/james-smith/README.md b/challenge-187/james-smith/README.md index 4bca52332b..f5528aed21 100644 --- a/challenge-187/james-smith/README.md +++ b/challenge-187/james-smith/README.md @@ -1,287 +1,77 @@ -[< Previous 185](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-185/james-smith) | -[Next 187 >](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-187/james-smith) +[< Previous 186](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-186/james-smith) | +[Next 188 >](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-188/james-smith) -# Ʈʯḗ Ŵꭂḵⱡʏ Chåɫleŋȅ 186 +# The Weekly Challenge 187 -Ỷȣ ʗầņ fɪƞẟ ḿồṛĕ ĩƞꬵõɽɯɑẖıọǹ ꬰƀȣƫ ðiŝ ŵꭂḵꭍ, ẚꬻḋ ṗʁeỽíȣẜ ẅꭂks cẗâỻɛŋɘṧ ẩṱ: +You can find more information about this weeks, and previous weeks challenges at: https://theweeklychallenge.org/ -Ïf ỿȣ ḁrẽ ṇọť aľɻəǻďƴ ẟƣŋ ðe ĉʮảꬸḽeŋḗ - íṯ ȉṥ ẫ ġỏoď plẵꭢ ʈⱺ ṗꭉaꬿŧiśe ɏỗůꭆ -**ƥěꭈⱡ** öṟ **ꭉakū**. Įƒ ȋt iȿ nóť **ṗḙɽl** oṙ **rakʊ** ẏȣ ƍȩvȅŀơƥ in - ỿȣ ĉẚṅ -ṡūḃꭑĭƫ šôȴuʈīoňẛ įṋ ẉɥḯċʯḝʋḕr ʟaŋʉaĝe ꭅȣ ꬵꭂⱡ cőmḟởrṯaƀłꬳ ẁið. +If you are not already doing the challenge - it is a good place to practise your +**perl** or **raku**. If it is not **perl** or **raku** you develop in - you can +submit solutions in whichever language you feel comfortable with. -Ȳȣ ɕañ ḟḭꬻḑ þe sȯḹȕțḭǫṋs ʯeɿe ốņ gɩʇḥùɓ ấţ: +You can find the solutions here on github at: -https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-186/james-smith +https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-187/james-smith -# Task 1 - Zip List +# Task 1 - Days Together -***You are given two list `@a` and `@b` of same size. Create a subroutine `sub zip(@a, @b)` that merge the two list as shown in the example below.*** +***Two friends, Foo and Bar gone on holidays seperately to the same city. You are given their schedule i.e. start date and end date.*** -## Solution - -This is a problem where perl signatures come into play. We use a signature so that we can -use arrays in call rather than references to arrays. The signature `(\@\@)` then converts -the arrays in the call into references. - -### Solution 1 - Simple code: - -Rather using a loop variable and select out of the two arrays -we loop through 1 and use a pointer to loop through the -other. - -```perl -sub zip (\@\@) { - my $c = 0; - map { $_, $_[1][$c++] } @{$_[0]} -} -``` - -### Solution 2 - Using a pointer for both arrays: - -This is the naive version where we have a counter and use it to index both arrays. - -The plus is that it is a single line, no need for a variable. +***To keep the task simple, the date is in the form DD-MM and all dates belong to the same calendar year i.e. between 01-01 and 31-12. Also the year is non-leap year and both dates are inclusive.*** -```perl -sub zipt (\@\@) { - map { $_[0][$_], $_[1][$_] } 0..@{$_[0]}-1; -} -``` - -### Solution 3 - Golfed code: - -Now I couldn't go a week without putting in some golf code - which is slightly -off the wall! We loop through one array and shift off the other - -As we are golfing we try and avoid new variables, we can therefore reuse/abuse `@_` -(if we are careful)... this is the reason for `local` which stops our changes -affecting the loop variable outside the function call. - -Not only does using `@_` avoid using `my` when we loop through the array as we -`shift` off the first entry we can use the bare `shift` as it assumes that the -array is `@_`... - -Finally we have to do `@{shift()}` as perl can't distinguish between this meaning -the variable `@shift` or `@{$_[-1]}`. - -```perl -sub zipx (\@\@) { - local($_,@_)=(shift,@{shift()}); - map{$_,shift}@$_ -} -``` - -## Performance - -With out original tests of up to 10 entries in the array we came up -with an ordering of `zip`, `zipt`, `zipx` as faster to slowest - -although with only about a 10-15% difference between all 3. - -We then tried with a larger array (initially 1000) and sptted that -`zipx` is now the fastest, about 20% faster than `zip` and 50% faster -then `zipt`. - -The break even point is around `35` entries in each array. So the -`zipx` is probably a better method to use as if the size is small -all are lightning fast - around 1 micro-second, but as the array -gets larger this gets around the millisecond - which could well be -more significant. - -# Task 2 - Unicode Makeover - -***You are given a string with possible unicode characters. Create a subroutine `sub makeover($str)` that replace the unicode characters with ascii equivalent. For this task, let us assume it only contains alphabets.*** +***Write a script to find out for the given schedule, how many days they spent together in the city, if at all.*** ## Solution -We could use packages/built in support for UTF-8. But where would be the fun in that... can we replicate this -in compact perl! +A slightly contrived one liner, which uses *closures* to perform the calculations without the need for intermediate variables... -We first need to define a data structure where we can define the mapping between unicode symbol and plain latin ASCII character. -We could use a straight hash. But as the blocks of letters are in Unicode 'code blocks' we can use this to define the arrays -more efficiently. +Working inward to outward, and bottom to top... -`%blocks` is a hash whose key is the numeric value of the first character in the block `ord($ch)`. -the second is a series of letter substitutions for that block. If the value in array is `?` then we assume there is -no direct mapping. +We: + * flatten the array refs into a single array; + * compute their year-day; + * from this we compute the last start & the first end; + * check to see if the last start < first end if so returns the value o/w returns 0. ```perl -%blocks = ( - 192 => [qw( - A A A A A A A C E E E E I I I I TH N O O O O O x O U U U U Y TH SS - ... - q ? ? dz ? dz ts ? tc ? ls lz ? ? h h)], - 7680 => [qw( - A a B b B b B b C c D d D d D d D d D d E e E e E e E e E e F f - ... - O o O o U u U u U u U u U u U u U u Y y Y y Y y Y y LL ll V v Y y)], - ... - 43824 => [qw( - a ae e e e f g l l l m n n ? ? c oe oe ee co co y r r r r r r r s n n - m m n x x x x x x x y ? ? ? ? ? lb ie ce uo a)], +sub days_together { + sub { $_>[1]<$_[0] ? 0 : $_[1]-$_[0]+1 }->( + sub { ( $_[2]>$_[0]?$_[2]:$_[0], $_[3]<$_[1]?$_[3]:$_[1] ) }->( + map { [ 0,0,31,59,90,120,151,181,212,243,273,304,334 ]->[substr $_,3] + substr$_,0,2 } + map { @{$_} } + @_ + ) + ) } ``` -Now note we allow "ligatures" & "diagraphs" in the array so there is a potential -for a 1-many mapping. (Diagraphs may be written as two letters, but sometimes the -letters are merged into a ligature, e.g. oe as in Phoenix; ss; ll in welsh ...) - -And now `makeover` - this might be seen as nasty code! But we will explain below - -```perl -sub makeover { join '', map { my $t = ord $_; - ( grep( { $_ ne '?' } - map { $t >= $_ && $t-$_ < @{$blocks{$_}} - ? $blocks{$_}[$t-$_] : () } - keys %blocks - ), chr $t )[0] -} split //, shift } - -``` - -``` - shift -> split -> map -> join -``` - -Remember with nested blocks we work backwards. The outer map is simple, we -split the parameter, and then process each character in turn, and join them -together. We split the string into chunks we assume it is a UTF-8 string, and -not a byte string, as the examples are the perl code - we can guarantee that -as we `use utf8`, for file/command line - we can use *e.g.* - -```perl -binmode(STDIN, "encoding(UTF-8)"); -``` - -There are similar was to ensure that database results are UTF-8 - -``` - keys -> map -> grep -``` - -Now for the inner loop - We loop through each block and see if the character -would be in that block - if it is we grab the mapped version of the character -- this is the `map` portion. This `map` returns at most one character. -We then `grep` out any `?` character - -We then add the original symbol to the list... So the results of the outer -bracket will be an array with one or two values - - `[ mapped, original ]` or `[ original ]`. - -So getting the zero-th element we have the mapped character if there is one or the original character if there isn't. - -We know output is going to be UTF-8 ans we changed the *binmode* -of STDOUT to be UTF-8. - -This is a bit messy and slow - so can we think of a different way of using our data structure: - -### A simpler solution!! - -Well we can convert the data structure into a hash... and see how the code works - this is an initial overhead -but each symbol is a lot quicker! - -```perl -my %map = map { - my $c = $_; - map { $_ eq '?' ? ($c++,$_) : ($c++) x 0 } - @{$blocks{$_}} -} keys %blocks; -``` - -This then gives us a `makeover` function of: - -```perl -sub makeover { join '', map { $map{ord $_}//$_ } split //, shift } -``` - -### Some examples and performance... - -Here are some examples.... - -``` - ÃÊÍÒÙ! => AEIOU! - âÊíÒÙ => aEiOU - Ƭȟȩ Ẇḕȅǩȴƴ Ćħąỻḝṅḡể => The Weekly Challenge -``` -With these three examples the 2nd method is 4-5x faster than the previous method... Pre-computing is always the way to go, -if you have a complex function and not too much memory is required to store the mappings. +# Task 2 - Split array -## Now lets go the other way... +***You are given a list of positive numbers, `@n`, having at least 3 numbers. Write a script to find the triplets `(a, b, c)` from the given list that satisfies the following rules.*** -This is interesting - but it was hard to write examples - so I thought why don't I go the other way and produce -the "decorated" code from the plain text - I find it weird calling it "`makeunder`" but as it is opposite over -`makeover` so be it. I think switching names would be more understandable. - -Now there are two ways we can do this - we can either just use the single character mappings or we can look to see if we -can include the ligatures/digraphs. - -We also add in a small random feature meaning we don't necessarily modify all characters... - -### Getting the mapping - -```perl -my @inv; -push @{$inv[length $map{$_}]{$map{$_}}},$_ for keys %map; -``` +## Solution -We have made this slightly more complex by splitting the mapping into two hashs - `$inv[1]` the mapping of characters and -`$inv[2]` the mapping of digraphs. +This is a permutation challenge, so we loop through the values with 3 nested loops. -### First pass no ligatures +By sorting we can make the assumption that `$a,$b,$c` are automatically sorted highest to lowest.. -This one is relatively simple - lookup character in list - if is mappable map it - if not just copy it, and we use the -`join map split` mode... +Each time through we use shift to get the first element of each loop until there are no values left. Note in this case we use `while` for the outer two loops... ```perl -sub makeunder_nolig { - join '', map { - $inv[1]{$_} && 0.8 > rand ? chr $inv[1]{$_}[rand @{$inv[1]{$_}}] : $_ - } split //,$_[0]; -} -``` - -### Now with ligatures - -```perl -sub makeunder { - my $res = ''; - my @T = split //,$_[0]; - while(@T) { - my $x = shift @T; - $res .= - @T && exists $inv[2]{$x.$T[0]} && 0.8 > rand - ? chr($inv[2]{$x.$T[0]}[rand @{$inv[2]{$x.$T[0]}}]).(shift @T)x 0 - : exists $inv[1]{$x} && 0.8 > rand - ? chr $inv[1]{$x}[rand @{$inv[1]{$x}}] - : $x +sub magical { + @_ = sort { $b <=> $a } @_; + my @max = (0); + while(@_>2) { + my($a,$b,@c)=@_; + while(@c) { + ($a+$b>$_) && ($b+$_>$a) && ($a+$_>$b) && ($a+$b+$_>$max[0]) && (@max=($a+$b+$_,$a,$b,$_)) for @c; + $b = shift @c; + } + shift; } - $res; + shift @max; + @max; } ``` - -We can't use the `join map split` model this time - as the `map` section is looking at one or two characters at a time. -So through the loop we first look for a ligature - if we have one we use that (OK - we might not with a random change). -If we don't we then try a single character, or if not fall through. - -**Notes:** We use our favourite `x 0` trick to shift the 2nd character from a digraph, without it affecting the output... - -Here is some output (this weeks challenges) you will already have seen some at the top of this document! - -``` -Ṫaṩḵ 1: Zįƥ Ḽiẛƭ -Ṧuɓṃïtŧȩƍ ḅꭅ: Ḿoḧǟmꭐaƌ Ṧ Ḁʼnẁẳr -Ỵồŭ äɺɞ ɡɪʌȅṅ țẅồ ƚīṧẖ @à ãɴḓ @b ōf ṥąꬺⱻ ṥĩȥe. - -Čʁeꭤťꬲ a ṧuɓꭆȣtȋñḛ ẜȕƃ ẕĩṗ(@ḁ, @ɓ) ðằṫ ṃềrĝe ðɚ ʈẇợ -łıẛƫ aṣ ẜhowṇ ɪn ðⱻ ềẋaꭑpɭȇ ḃʚꬸȯw. - -Ṭẫꭍḳ 2: Ʊꬼıꭄȡɜ Ṁắƙẹȱỽėȓ -ſȗḇɯïţⱦɜȡ bʏ: Ṁổɦẩɰṃåḋ S Ấꬼwǡɾ -Ÿȣ äꭋe ǥiṿȩȵ ȃ śẖȑḭnĝ ẁịʇḧ ṕȱṣẝɨḇlé uņĩꭄdě ċȟắꭇäȼṱḕȓȿ. - -Çɹḛaƭe ậ ẝửḃꭊôuṫiꭎḗ ṩṳƃ ɯắkeṓỽeꭆ($ṩẖꭋ) ðat rȩpḷāče ƫḣẹ -uꭎịʗɔdē cḫắɾȁḉțễꭈʂ ẁĭð aẜḉɨĭ ɘɋữǐṿaļėꭎť. Ƒỏꭊ ðis ṯꭤśk, -ḷeƭ ǘʂ aʂṣụɯȩ ḯŧ ȭṉḹꭅ ꭄṋʈấïṋș alṕẗǎƀeʦ. -``` diff --git a/challenge-187/james-smith/blog.txt b/challenge-187/james-smith/blog.txt new file mode 100644 index 0000000000..027b0a1a9e --- /dev/null +++ b/challenge-187/james-smith/blog.txt @@ -0,0 +1 @@ +https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-187/james-smith diff --git a/challenge-187/james-smith/perl/ch-1.pl b/challenge-187/james-smith/perl/ch-1.pl new file mode 100644 index 0000000000..a79e0c55ad --- /dev/null +++ b/challenge-187/james-smith/perl/ch-1.pl @@ -0,0 +1,31 @@ +#!/usr/local/bin/perl + +use strict; + +use warnings; +use feature qw(say); +use Test::More; +use Benchmark qw(cmpthese timethis); +use Data::Dumper qw(Dumper); + +my @TESTS = ( + [ ['12-01','20-01'], ['15-01','18-01'], 4 ] , + [ ['02-03','12-03'], ['13-03','14-03'], 0 ], + [ ['02-03','12-03'], ['11-03','15-03'], 2 ], + [ ['30-03','05-04'], ['28-03','02-04'], 4 ], +); + +is( days_together($_->[0],$_->[1]), $_->[2] ) foreach @TESTS; + +done_testing(); + +sub days_together { + sub { $_>[1]<$_[0] ? 0 : $_[1]-$_[0]+1 }->( + sub { ( $_[2]>$_[0]?$_[2]:$_[0], $_[3]<$_[1]?$_[3]:$_[1] ) }->( + map { [ 0,0,31,59,90,120,151,181,212,243,273,304,334 ]->[substr $_,3] + substr$_,0,2 } + map { @{$_} } + @_ + ) + ) +} + diff --git a/challenge-187/james-smith/perl/ch-2.pl b/challenge-187/james-smith/perl/ch-2.pl new file mode 100644 index 0000000000..18d5af1e0c --- /dev/null +++ b/challenge-187/james-smith/perl/ch-2.pl @@ -0,0 +1,36 @@ +#!/usr/local/bin/perl + +use strict; + +use warnings; +use feature qw(say); +use Test::More; +use Benchmark qw(cmpthese timethis); +use Data::Dumper qw(Dumper); + +my @TESTS = ( + [ [1,2,3,2], '3 2 2' ], + [ [1,3,2], '' ], + [ [1,1,2,3], '' ], + [ [2,4,3], '4 3 2' ], +); + +is( "@{[magical(@{$_->[0]})]}", $_->[1] ) foreach @TESTS; + +done_testing(); + +sub magical { + @_ = sort { $b<=>$a } @_; + my @max = (0); + while(@_>2) { + my($a,$b,@c)=@_; + while(@c) { + ($a+$b>$_) && ($b+$_>$a) && ($a+$_>$b) && ($a+$b+$_>$max[0]) && (@max=($a+$b+$_,$a,$b,$_)) for @c; + $b = shift @c; + } + shift; + } + shift @max; + @max; +} + -- cgit From b78d0eadcb43c7cfc737ba31857af95319031b4e Mon Sep 17 00:00:00 2001 From: Mark <53903062+andemark@users.noreply.github.com> Date: Mon, 17 Oct 2022 07:31:54 +0000 Subject: Challenge 187 Solutions (Raku) --- challenge-187/mark-anderson/raku/ch-1.raku | 24 ++++++++++++++++++++++++ challenge-187/mark-anderson/raku/ch-2.raku | 20 ++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 challenge-187/mark-anderson/raku/ch-1.raku create mode 100644 challenge-187/mark-anderson/raku/ch-2.raku diff --git a/challenge-187/mark-anderson/raku/ch-1.raku b/challenge-187/mark-anderson/raku/ch-1.raku new file mode 100644 index 0000000000..e29d0a0649 --- /dev/null +++ b/challenge-187/mark-anderson/raku/ch-1.raku @@ -0,0 +1,24 @@ +#!/usr/bin/env raku +use Test; + +is days-together({:SD('12-01'), :ED('20-01')}, {:SD('15-01'), :ED('18-01')}), 4; +is days-together({:SD('02-03'), :ED('12-03')}, {:SD('13-03'), :ED('14-03')}), 0; +is days-together({:SD('02-03'), :ED('12-03')}, {:SD('11-03'), :ED('15-03')}), 2; +is days-together({:SD('30-03'), :ED('05-04')}, {:SD('28-03'), :ED('02-04')}), 4; + +sub days-together(%foo, %bar) +{ + my $a := ('01','02'...'31'), ('01','02'...'28'), ('01','02'...'31'), + ('01','02'...'30'), ('01','02'...'31'), ('01','02'...'30'), + ('01','02'...'31'), ('01','02'...'31'), ('01','02'...'30'), + ('01','02'...'31'), ('01','02'...'30'), ('01','02'...'31'); + + my $b := '-01','-02'...'-12'; + + my $c := ($a >>~>> $b).flat.List; + + my $d := map { $_ if %foo ff %foo }, $c; + my $e := map { $_ if %bar ff %bar }, $c; + + ($d (&) $e).elems +} diff --git a/challenge-187/mark-anderson/raku/ch-2.raku b/challenge-187/mark-anderson/raku/ch-2.raku new file mode 100644 index 0000000000..8091a86593 --- /dev/null +++ b/challenge-187/mark-anderson/raku/ch-2.raku @@ -0,0 +1,20 @@ +#!/usr/bin/env raku +use Test; + +is-deeply magical-triplets(1, 2, 3, 2), (3, 2, 2); +is-deeply magical-triplets(1, 3, 2), (); +is-deeply magical-triplets(1, 1, 2, 3), (); +is-deeply magical-triplets(2, 4, 3), (4, 3, 2); + +sub magical-triplets(+$list) +{ + $list.combinations(3) + .map({ |.permutations }) + .unique(with => &[eqv]) + .flat + .grep({ [and] $^a + $^b > $^c, + $^b + $^c > $^a, + $^a + $^c > $^b }) + andthen + .elems ?? .max !! Empty.List +} -- cgit From daecb450fef6e0d653f7c6d49cb85d9ea670826c Mon Sep 17 00:00:00 2001 From: Luca Ferrari Date: Mon, 17 Oct 2022 09:45:10 +0200 Subject: Task 1 done --- challenge-187/luca-ferrari/raku/ch-1.p6 | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 challenge-187/luca-ferrari/raku/ch-1.p6 diff --git a/challenge-187/luca-ferrari/raku/ch-1.p6 b/challenge-187/luca-ferrari/raku/ch-1.p6 new file mode 100644 index 0000000000..4f795ef3c8 --- /dev/null +++ b/challenge-187/luca-ferrari/raku/ch-1.p6 @@ -0,0 +1,24 @@ +#!raku + +# Perl Weekly Challenge 187 + +sub MAIN( Str $start-foo, Str $end-foo, Str $start-bar, Str $end-bar ) { + + $start-foo ~~ / ^ ( \d ** 2 ) '-' ( \d ** 2 ) $ /; + my $foo-days-start = DateTime.new: year => 2022, day => $/[0], month => $/[1]; + $end-foo ~~ / ^ (\d ** 2) '-' (\d **2) $ /; + my $foo-days-end = DateTime.new: year => 2022, day => $/[0], month => $/[1]; + + $start-bar ~~ / ^ ( \d ** 2 ) '-' ( \d ** 2 ) $ /; + my $bar-days-start = DateTime.new: year => 2022, day => $/[0], month => $/[1]; + $end-bar ~~ / ^ ( \d ** 2 ) '-' ( \d ** 2 ) $ /; + my $bar-days-end = DateTime.new: year => 2022, day => $/[0], month => $/[1]; + + my $days = 0; + while ( $foo-days-start < $foo-days-end ) { + $days++ if ( $bar-days-end >= $foo-days-start >= $bar-days-start ); + $foo-days-start .= later( days => 1 ); + } + + say $days; +} -- cgit From 821cd43fe948e3d5ae68aa1e3adaec3bbefca309 Mon Sep 17 00:00:00 2001 From: James Smith Date: Mon, 17 Oct 2022 08:46:19 +0100 Subject: Update README.md --- challenge-187/james-smith/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/challenge-187/james-smith/README.md b/challenge-187/james-smith/README.md index f5528aed21..152fb5f1a3 100644 --- a/challenge-187/james-smith/README.md +++ b/challenge-187/james-smith/README.md @@ -37,9 +37,17 @@ We: ```perl sub days_together { + # *4* If start [0] > end[1] then return the difference + 1 otherwise return 0 sub { $_>[1]<$_[0] ? 0 : $_[1]-$_[0]+1 }->( + # *3* Calculate max start & min end... + # If bar->start [2] > foo->start [0] then overlap->start = bar->start else it's foo->start + # If bar->end [3] < foo->end [1] then overlap->end = bar->end else it's foo->end sub { ( $_[2]>$_[0]?$_[2]:$_[0], $_[3]<$_[1]?$_[3]:$_[1] ) }->( + # *2* Compute year day - array contains offsets for the start of each month [ there is a + # padding 0 so we don't have to adjust month by 1... map { [ 0,0,31,59,90,120,151,181,212,243,273,304,334 ]->[substr $_,3] + substr$_,0,2 } + # *1* Flatten two arrays into one... could have written this as @{$_[0]}, @{$_[1]} to avoid + # the map. map { @{$_} } @_ ) -- cgit From 683a336d675d35a38cfb496d21a449977d9fcaef Mon Sep 17 00:00:00 2001 From: Luca Ferrari Date: Mon, 17 Oct 2022 09:54:11 +0200 Subject: Task 2 done --- challenge-187/luca-ferrari/raku/ch-2.p6 | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 challenge-187/luca-ferrari/raku/ch-2.p6 diff --git a/challenge-187/luca-ferrari/raku/ch-2.p6 b/challenge-187/luca-ferrari/raku/ch-2.p6 new file mode 100644 index 0000000000..9253317f2d --- /dev/null +++ b/challenge-187/luca-ferrari/raku/ch-2.p6 @@ -0,0 +1,30 @@ +#!raku + +# Perl Weekly Challenge 187 + +sub MAIN( *@n where { @n.grep( * ~~ Int ).elems == @n.elems } ) { + + my $max = 0; + my @triplet; + for 0 ..^ @n.elems -> $index-a { + my $a = @n[ $index-a ].Int; + + for $index-a ^..^ @n.elems -> $index-b { + my $b = @n[ $index-b ].Int; + + for $index-b ^..^ @n.elems -> $index-c { + my $c = @n[ $index-c ].Int; + + if ( $max <= $a + $b + $c + && ( $a + $b ) > $c + && ( $b + $c ) > $a + && ( $a + $c ) > $b ) { + @triplet = $a, $b, $c; + $max = $a + $b + $c; + } + } + } + } + + @triplet.sort.say if ( @triplet ); +} -- cgit From 87ba9f84bd1c938006b0b8de1ec94cd058fd7e9e Mon Sep 17 00:00:00 2001 From: James Smith Date: Mon, 17 Oct 2022 08:58:28 +0100 Subject: Update README.md --- challenge-187/james-smith/README.md | 49 ++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/challenge-187/james-smith/README.md b/challenge-187/james-smith/README.md index 152fb5f1a3..6e296e8472 100644 --- a/challenge-187/james-smith/README.md +++ b/challenge-187/james-smith/README.md @@ -25,7 +25,17 @@ https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-187/ja ## Solution -A slightly contrived one liner, which uses *closures* to perform the calculations without the need for intermediate variables... +A slightly contrived one liner, which uses *self-executing closures* to perform the calculations without the need for creating intermediate variables. + +We are used to using *closures* or *anonymous functions* as callbacks in various functions - like `sort`, `map`, `grep` etc, but we can also use them +as self executing functions `sub { ..code.. }->( ..data.. )`, this is similar to the approach used in javascript to alias methods/variables. + +e.g. +```php +(function($){ + $.fn.function_name = function(x){}; +})(jQuery); +``` Working inward to outward, and bottom to top... @@ -37,24 +47,41 @@ We: ```perl sub days_together { - # *4* If start [0] > end[1] then return the difference + 1 otherwise return 0 sub { $_>[1]<$_[0] ? 0 : $_[1]-$_[0]+1 }->( - # *3* Calculate max start & min end... - # If bar->start [2] > foo->start [0] then overlap->start = bar->start else it's foo->start - # If bar->end [3] < foo->end [1] then overlap->end = bar->end else it's foo->end - sub { ( $_[2]>$_[0]?$_[2]:$_[0], $_[3]<$_[1]?$_[3]:$_[1] ) }->( - # *2* Compute year day - array contains offsets for the start of each month [ there is a - # padding 0 so we don't have to adjust month by 1... - map { [ 0,0,31,59,90,120,151,181,212,243,273,304,334 ]->[substr $_,3] + substr$_,0,2 } - # *1* Flatten two arrays into one... could have written this as @{$_[0]}, @{$_[1]} to avoid - # the map. + # *4* If start [0] > end[1] then return the difference + 1 otherwise return 0 + + sub { ( $_[2] > $_[0] ? $_[2] : $_[0], $_[3] < $_[1] ? $_[3] : $_[1] ) }->( + # *3* Calculate max start & min end... + # If bar->start [2] > foo->start [0] then overlap->start = bar->start else it's foo->start + # If bar->end [3] < foo->end [1] then overlap->end = bar->end else it's foo->end + + map { [ 0,0,31,59,90,120,151,181,212,243,273,304,334 ]->[ substr $_,3 ] + substr $_,0,2 } + # *2* Compute year day - array contains offsets for the start of each month [ there is a + # padding 0 so we don't have to adjust month by 1... + map { @{$_} } + # *1* Flatten two arrays into one... could have written this as @{$_[0]}, @{$_[1]} to avoid + # the map. + @_ ) ) } ``` +and now without the comments: + +```perl +sub days_together { + sub { $_>[1]<$_[0] ? 0 : $_[1]-$_[0]+1 }->( + sub { ( $_[2] > $_[0] ? $_[2] : $_[0], $_[3] < $_[1] ? $_[3] : $_[1] ) }->( + map { [ 0,0,31,59,90,120,151,181,212,243,273,304,334 ]->[ substr $_,3 ] + substr $_,0,2 } + map { @{$_} } + @_ + ) + ) +} +``` # Task 2 - Split array ***You are given a list of positive numbers, `@n`, having at least 3 numbers. Write a script to find the triplets `(a, b, c)` from the given list that satisfies the following rules.*** -- cgit From 3e5e3b01d75aacc68e893eceddd7d0e406680c0a Mon Sep 17 00:00:00 2001 From: James Smith Date: Mon, 17 Oct 2022 10:15:56 +0100 Subject: Update README.md --- challenge-187/james-smith/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/challenge-187/james-smith/README.md b/challenge-187/james-smith/README.md index 6e296e8472..b1fbbf2150 100644 --- a/challenge-187/james-smith/README.md +++ b/challenge-187/james-smith/README.md @@ -47,7 +47,7 @@ We: ```perl sub days_together { - sub { $_>[1]<$_[0] ? 0 : $_[1]-$_[0]+1 }->( + sub { $_[1]<$_[0] ? 0 : $_[1]-$_[0]+1 }->( # *4* If start [0] > end[1] then return the difference + 1 otherwise return 0 sub { ( $_[2] > $_[0] ? $_[2] : $_[0], $_[3] < $_[1] ? $_[3] : $_[1] ) }->( -- cgit From da718a3c5dbdbde6b33b9430de69a078b1b27223 Mon Sep 17 00:00:00 2001 From: drbaggy Date: Mon, 17 Oct 2022 10:16:34 +0100 Subject: whitespace --- challenge-187/james-smith/perl/ch-1.pl | 2 +- challenge-187/james-smith/perl/ch-2.pl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/challenge-187/james-smith/perl/ch-1.pl b/challenge-187/james-smith/perl/ch-1.pl index a79e0c55ad..320dfc1da2 100644 --- a/challenge-187/james-smith/perl/ch-1.pl +++ b/challenge-187/james-smith/perl/ch-1.pl @@ -20,7 +20,7 @@ is( days_together($_->[0],$_->[1]), $_->[2] ) foreach @TESTS; done_testing(); sub days_together { - sub { $_>[1]<$_[0] ? 0 : $_[1]-$_[0]+1 }->( + sub { $_[1]<$_[0] ? 0 : $_[1]-$_[0]+1 }->( sub { ( $_[2]>$_[0]?$_[2]:$_[0], $_[3]<$_[1]?$_[3]:$_[1] ) }->( map { [ 0,0,31,59,90,120,151,181,212,243,273,304,334 ]->[substr $_,3] + substr$_,0,2 } map { @{$_} } diff --git a/challenge-187/james-smith/perl/ch-2.pl b/challenge-187/james-smith/perl/ch-2.pl index 18d5af1e0c..e08218ad26 100644 --- a/challenge-187/james-smith/perl/ch-2.pl +++ b/challenge-187/james-smith/perl/ch-2.pl @@ -20,7 +20,7 @@ is( "@{[magical(@{$_->[0]})]}", $_->[1] ) foreach @TESTS; done_testing(); sub magical { - @_ = sort { $b<=>$a } @_; + @_ = sort { $b <=> $a } @_; my @max = (0); while(@_>2) { my($a,$b,@c)=@_; -- cgit From e1b6e75c2e06431f61f1537af5a1b387b6bd72f9 Mon Sep 17 00:00:00 2001 From: Luca Ferrari Date: Mon, 17 Oct 2022 11:28:12 +0200 Subject: Fix task 1 --- challenge-187/luca-ferrari/raku/ch-1.p6 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/challenge-187/luca-ferrari/raku/ch-1.p6 b/challenge-187/luca-ferrari/raku/ch-1.p6 index 4f795ef3c8..792c650429 100644 --- a/challenge-187/luca-ferrari/raku/ch-1.p6 +++ b/challenge-187/luca-ferrari/raku/ch-1.p6 @@ -15,9 +15,15 @@ sub MAIN( Str $start-foo, Str $end-foo, Str $start-bar, Str $end-bar ) { my $bar-days-end = DateTime.new: year => 2022, day => $/[0], month => $/[1]; my $days = 0; - while ( $foo-days-start < $foo-days-end ) { - $days++ if ( $bar-days-end >= $foo-days-start >= $bar-days-start ); - $foo-days-start .= later( days => 1 ); + my $start = $foo-days-start >= $bar-days-start ?? $bar-days-start !! $foo-days-start; + my $end = $foo-days-end >= $bar-days-end ?? $foo-days-end !! $bar-days-end; + + while ( $start < $end ) { + $days++ if ( $start >= $foo-days-start + && $start <= $foo-days-end + && $start >= $bar-days-start + && $start <= $bar-days-end ); + $start .= later( days => 1 ); } say $days; -- cgit From 1d23f91d86e7ebb5291c17fc99ec0fc2ca48b64a Mon Sep 17 00:00:00 2001 From: Roger Bell_West Date: Mon, 17 Oct 2022 11:05:10 +0100 Subject: Solutions for challenge #187 --- challenge-187/roger-bell-west/javascript/ch-1.js | 54 ++++++ challenge-187/roger-bell-west/javascript/ch-2.js | 87 +++++++++ challenge-187/roger-bell-west/kotlin/ch-1.kt | 49 +++++ challenge-187/roger-bell-west/kotlin/ch-2.kt | 51 ++++++ challenge-187/roger-bell-west/lua/ch-2.lua | 97 ++++++++++ challenge-187/roger-bell-west/perl/ch-1.pl | 45 +++++ challenge-187/roger-bell-west/perl/ch-2.pl | 43 +++++ challenge-187/roger-bell-west/postscript/ch-1.ps | 155 ++++++++++++++++ challenge-187/roger-bell-west/postscript/ch-2.ps | 222 +++++++++++++++++++++++ challenge-187/roger-bell-west/python/ch-1.py | 43 +++++ challenge-187/roger-bell-west/python/ch-2.py | 40 ++++ challenge-187/roger-bell-west/raku/ch-1.p6 | 40 ++++ challenge-187/roger-bell-west/raku/ch-2.p6 | 38 ++++ challenge-187/roger-bell-west/ruby/ch-1.rb | 44 +++++ challenge-187/roger-bell-west/ruby/ch-2.rb | 44 +++++ challenge-187/roger-bell-west/rust/ch-1.rs | 40 ++++ challenge-187/roger-bell-west/rust/ch-2.rs | 41 +++++ 17 files changed, 1133 insertions(+) create mode 100755 challenge-187/roger-bell-west/javascript/ch-1.js create mode 100755 challenge-187/roger-bell-west/javascript/ch-2.js create mode 100644 challenge-187/roger-bell-west/kotlin/ch-1.kt create mode 100644 challenge-187/roger-bell-west/kotlin/ch-2.kt create mode 100755 challenge-187/roger-bell-west/lua/ch-2.lua create mode 100755 challenge-187/roger-bell-west/perl/ch-1.pl create mode 100755 challenge-187/roger-bell-west/perl/ch-2.pl create mode 100644 challenge-187/roger-bell-west/postscript/ch-1.ps create mode 100644 challenge-187/roger-bell-west/postscript/ch-2.ps create mode 100755 challenge-187/roger-bell-west/python/ch-1.py create mode 100755 challenge-187/roger-bell-west/python/ch-2.py create mode 100755 challenge-187/roger-bell-west/raku/ch-1.p6 create mode 100755 challenge-187/roger-bell-west/raku/ch-2.p6 create mode 100755 challenge-187/roger-bell-west/ruby/ch-1.rb create mode 100755 challenge-187/roger-bell-west/ruby/ch-2.rb create mode 100644 challenge-187/roger-bell-west/rust/ch-1.rs create mode 100644 challenge-187/roger-bell-west/rust/ch-2.rs diff --git a/challenge-187/roger-bell-west/javascript/ch-1.js b/challenge-187/roger-bell-west/javascript/ch-1.js new file mode 100755 index 0000000000..e00346b98f --- /dev/null +++ b/challenge-187/roger-bell-west/javascript/ch-1.js @@ -0,0 +1,54 @@ +#! /usr/bin/node + +"use strict" + +function s2date(ds) { + let dm = ds.split("-"); + if (dm.length == 2) { + return Date.UTC(2022, parseInt(dm[1])-1, parseInt(dm[0]), 0, 0, 0, 0)/86400000; + } +} + +function daystogether(a, b) { + let starts = [s2date(a[0]), s2date(b[0])]; + starts.sort(function(a,b) { + return a-b; + }); + let ends = [s2date(a[1]), s2date(b[1])]; + ends.sort(function(a,b) { + return a-b; + }); + if (ends[0] >= starts[1]) { + return ends[0]-starts[1]+1; + } else { + return 0; + } +} + +if (daystogether(["12-01", "20-01"], ["15-01", "18-01"]) == 4) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); + +if (daystogether(["02-03", "12-03"], ["13-03", "14-03"]) == 0) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); + +if (daystogether(["02-03", "12-03"], ["11-03", "15-03"]) == 2) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); + +if (daystogether(["30-03", "05-04"], ["28-03", "02-04"]) == 4) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write("\n"); diff --git a/challenge-187/roger-bell-west/javascript/ch-2.js b/challenge-187/roger-bell-west/javascript/ch-2.js new file mode 100755 index 0000000000..67529e6246 --- /dev/null +++ b/challenge-187/roger-bell-west/javascript/ch-2.js @@ -0,0 +1,87 @@ +#! /usr/bin/node + +"use strict" + +// by Frank Tan +// https://stackoverflow.com/questions/38400594/javascript-deep-comparison +function deepEqual(a,b) +{ + if( (typeof a == 'object' && a != null) && + (typeof b == 'object' && b != null) ) + { + var count = [0,0]; + for( var key in a) count[0]++; + for( var key in b) count[1]++; + if( count[0]-count[1] != 0) {return false;} + for( var key in a) + { + if(!(key in b) || !deepEqual(a[key],b[key])) {return false;} + } + for( var key in b) + { + if(!(key in a) || !deepEqual(b[key],a[key])) {return false;} + } + return true; + } + else + { + return a === b; + } +} + +function magicaltriplets(a) { + let out = []; + let mv = 0; + for (let ai = 0; ai < a.length-2; ai++) { + for (let bi = ai+1; bi < a.length-1; bi++) { + for (let ci = bi+1; ci < a.length; ci++) { + if (a[ai] + a[bi] > a[ci] && + a[bi] + a[ci] > a[ai] && + a[ai] + a[ci] > a[bi]) { + let v = a[ai] + a[bi] + a[ci]; + if (v > mv) { + mv = v; + out = [a[ai], a[bi], a[ci]]; + } + } + } + } + } + out.sort(function(a,b) { + return b-a; + }); + return out; +} + +if (deepEqual(magicaltriplets([1, 2, 3, 2]), + [3, 2, 2])) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); + +if (deepEqual(magicaltriplets([1, 3, 2]), + [])) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); + +if (deepEqual(magicaltriplets([1, 1, 2, 3]), + [])) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} +process.stdout.write(" "); + +if (deepEqual(magicaltriplets([2, 4, 3]), + [4, 3, 2])) { + process.stdout.write("Pass"); +} else { + process.stdout.write("FAIL"); +} + +process.stdout.write("\n"); diff --git a/challenge-187/roger-bell-west/kotlin/ch-1.kt b/challenge-187/roger-bell-west/kotlin/ch-1.kt new file mode 100644 index 0000000000..299c4db50c --- /dev/null +++ b/challenge-187/roger-bell-west/kotlin/ch-1.kt @@ -0,0 +1,49 @@ +import java.time.LocalDate +import java.time.format.DateTimeFormatter +import java.time.temporal.ChronoUnit + +fun s2date(ds: String): LocalDate { + val formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy") + return LocalDate.parse(ds + "-2022", formatter) +} + +fun daystogether(a: List, b: List): Int { + var starts = listOf(s2date(a[0]), s2date(b[0])).sorted() + var ends = listOf(s2date(a[1]), s2date(b[1])).sorted() + if (ends[0] >= starts[1]) { + return ChronoUnit.DAYS.between(starts[1], ends[0]).toInt()+1 + } else { + return 0 + } +} + +fun main() { + if (daystogether(listOf("12-01", "20-01"), listOf("15-01", "18-01")) == + 4) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + if (daystogether(listOf("02-03", "12-03"), listOf("13-03", "14-03")) == + 0) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + if (daystogether(listOf("02-03", "12-03"), listOf("11-03", "15-03")) == + 2) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + if (daystogether(listOf("30-03", "05-04"), listOf("28-03", "02-04")) == + 4) { + print("Pass") + } else { + print("FAIL") + } + println("") +} diff --git a/challenge-187/roger-bell-west/kotlin/ch-2.kt b/challenge-187/roger-bell-west/kotlin/ch-2.kt new file mode 100644 index 0000000000..93fc98e9d7 --- /dev/null +++ b/challenge-187/roger-bell-west/kotlin/ch-2.kt @@ -0,0 +1,51 @@ +fun magicaltriplets(a: List): List { + var out = listOf() + var mv = 0 + for (ai in 0..a.size-3) { + for (bi in ai+1..a.size-2) { + for (ci in bi+1..a.size-1) { + if (a[ai] + a[bi] > a[ci] && + a[bi] + a[ci] > a[ai] && + a[ai] + a[ci] > a[bi]) { + var v = a[ai] + a[bi] + a[ci] + if (v > mv) { + mv = v + out = listOf(a[ai], a[bi], a[ci]) + } + } + } + } + } + return out.sorted().reversed().toList() +} + +fun main() { + if (magicaltriplets(listOf(1, 2, 3, 2)) == + listOf(3, 2, 2)) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + if (magicaltriplets(listOf(1, 3, 2)) == + listOf()) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + if (magicaltriplets(listOf(1, 1, 2, 3)) == + listOf()) { + print("Pass") + } else { + print("FAIL") + } + print(" ") + if (magicaltriplets(listOf(2, 4, 3)) == + listOf(4, 3, 2)) { + print("Pass") + } else { + print("FAIL") + } + println("") +} diff --git a/challenge-187/roger-bell-west/lua/ch-2.lua b/challenge-187/roger-bell-west/lua/ch-2.lua new file mode 100755 index 0000000000..8aac5559d1 --- /dev/null +++ b/challenge-187/roger-bell-west/lua/ch-2.lua @@ -0,0 +1,97 @@ +#! /usr/bin/lua + +-- by Michael Anderson at +-- https://stackoverflow.com/questions/8722620/comparing-two-index-tables-by-index-value-in-lua +function recursive_compare(t1,t2) + -- Use usual comparison first. + if t1==t2 then return true end + -- We only support non-default behavior for tables + if (type(t1)~="table") then return false end + -- They better have the same metatables + local mt1 = getmetatable(t1) + local mt2 = getmetatable(t2) + if( not recursive_compare(mt1,mt2) ) then return false end + + -- Check each key-value pair + -- We have to do this both ways in case we miss some. + -- TODO: Could probably be smarter and not check those we've + -- already checked though! + for k1,v1 in pairs(t1) do + local v2 = t2[k1] + if( not recursive_compare(v1,v2) ) then return false end + end + for k2,v2 in pairs(t2) do + local v1 = t1[k2] + if( not recursive_compare(v1,v2) ) then return false end + end + + return true +end +-- by hookenz at +-- https://stackoverflow.com/questions/9168058/how-to-dump-a-table-to-console +function dump(o) + if type(o) == 'table' then + local s = '{ ' + for k,v in pairs(o) do + if type(k) ~= 'number' then k = '"'..k..'"' end + s = s .. '['..k..'] = ' .. dump(v) .. ',' + end + return s .. '} ' + else + return tostring(o) + end +end + +function magicaltriplets(a) + local out = {} + local mv = 0 + for ai = 1,#a-2 do + for bi = ai+1,#a-1 do + for ci = bi+1,#a do + if a[ai] + a[bi] > a[ci] and + a[bi] + a[ci] > a[ai] and + a[ai] + a[ci] > a[bi] then + local v = a[ai] + a[bi] + a[ci] + if v > mv then + mv = v + out = {a[ai], a[bi], a[ci]} + end + end + end + end + end + table.sort(out, function (i,j) return j < i end) + return out +end + +if (recursive_compare(magicaltriplets({1, 2, 3, 2}), + {3, 2, 2})) then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if (recursive_compare(magicaltriplets({1, 3, 2}), + {})) then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if (recursive_compare(magicaltriplets({1, 1, 2, 3}), + {})) then + io.write("Pass") +else + io.write("FAIL") +end +io.write(" ") + +if (recursive_compare(magicaltriplets({2, 4, 3}), + {4, 3, 2})) then + io.write("Pass") +else + io.write("FAIL") +end +print("") diff --git a/challenge-187/roger-bell-west/perl/ch-1.pl b/challenge-187/roger-bell-west/perl/ch-1.pl new file mode 100755 index 0000000000..52ec4111b9 --- /dev/null +++ b/challenge-187/roger-bell-west/perl/ch-1.pl @@ -0,0 +1,45 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use experimental 'signatures'; + +use DateTime; +use DateTime::Format::Strptime; + +use Test::More tests => 4; + +is_deeply(daystogether(["12-01", "20-01"], ["15-01", "18-01"]), + 4, + 'example 1'); + +is_deeply(daystogether(["02-03", "12-03"], ["13-03", "14-03"]), + 0, + 'example 2'); + +is_deeply(daystogether(["02-03", "12-03"], ["11-03", "15-03"]), + 2, + 'example 3'); + +is_deeply(daystogether(["30-03", "05-04"], ["28-03", "02-04"]), + 4, + 'example 4'); + +sub daystogether($a,$b) { + my @starts = sort (s2date($a->[0]), s2date($b->[0])); + my @ends = sort (s2date($a->[1]), s2date($b->[1])); + if ($ends[0] > $starts[1]) { + return $ends[0]->delta_days($starts[1])->in_units('days')+1; + } else { + return 0; + } +} + +sub s2date($ds) { + my $strp = DateTime::Format::Strptime->new( + pattern => '%d-%m-%Y', + strict => 1, + time_zone => 'GMT', + ); + return $strp->parse_datetime("$ds-2022"); +} diff --git a/challenge-187/roger-bell-west/perl/ch-2.pl b/challenge-187/roger-bell-west/perl/ch-2.pl new file mode 100755 index 0000000000..f0f55a7735 --- /dev/null +++ b/challenge-187/roger-bell-west/perl/ch-2.pl @@ -0,0 +1,43 @@ +#! /usr/bin/perl + +use strict; +use warnings; +use experimental 'signatures'; + +use Test::More tests => 4; + +use Algorithm::Combinatorics qw(combinations); + +is_deeply(magicaltriplets([1, 2, 3, 2]), + [3, 2, 2], + 'example 1'); + +is_deeply(magicaltriplets([1, 3, 2]), + [], + 'example 2'); + +is_deeply(magicaltriplets([1, 1, 2, 3]), + [], + 'example 3'); + +is_deeply(magicaltriplets([2, 4, 3]), + [4, 3, 2], + 'example 4'); + +sub magicaltriplets($a) { + my $out = []; + my $mv = 0; + my $iter = combinations($a, 3); + while (my $b = $iter->next) { + if ($b->[0] + $b->[1] > $b->[2] && + $b->[1] + $b->[2] > $b->[0] && + $b->[0] + $b->[2] > $b->[1]) { + my $v = $b->[0] + $b->[1] + $b->[2]; + if ($v > $mv) { + $mv = $v; + $out = [$b->[0], $b->[1], $b->[2]]; + } + } + } + return [reverse sort @{$out}]; +} diff --git a/challenge-187/roger-bell-west/postscript/ch-1.ps b/challenge-187/roger-bell-west/postscript/ch-1.ps new file mode 100644 index 0000000000..3344baa22e --- /dev/null +++ b/challenge-187/roger-bell-west/postscript/ch-1.ps @@ -0,0 +1,155 @@ +%!PS + +% begin included library code +% see https://github.com/Firedrake/postscript-libraries/ +/quicksort { % [ a c b ] -> [ a b c ] + 1 dict begin + /arr exch def + 0 arr length 1 sub quicksort.main + arr + end +} bind def + +/quicksort.partition { + 3 dict begin + /pivot arr hi lo add 2 idiv get def + /i lo 1 sub def + /j hi 1 add def + { + { + /i i 1 add def + arr i get pivot ge { + exit + } if + } loop + { + /j j 1 sub def + arr j get pivot le { + exit + } if + } loop + i j ge { + j + exit + } if + i j quicksort.swap + } loop + end +} bind def + +/quicksort.main { % lo hi -> (null) + 3 dict begin + /hi exch def + /lo exch def + /xit false def + lo 0 lt { + /xit true def + } if + hi 0 lt { + /xit true def + } if + lo hi ge { + /xit true def + } if + xit not { + /p quicksort.partition def + lo p quicksort.main + p 1 add hi quicksort.main + } if + end +} bind def + +/quicksort.swap { + 2 dict begin + /bi exch def + /ai exch def + arr ai get + arr bi get + arr exch ai exch put + arr exch bi exch put + end +} bind def + +/test.end { + ( ) print + test.count 0 gt { + (Passed ) print + test.pass (...) cvs print + (/) print + test.count (...) cvs print + ( \() print + test.pass 100 mul test.count idiv (...) cvs print + (%\)) print + (\r\n) print + } if +} bind def + +/ymd2jd { + 4 dict begin + aload pop + /d exch def + /m exch def + /y exch def + /mn m 14 sub 12 idiv def + y 4800 add mn add 1461 mul 4 idiv + mn 12 mul neg 2 sub m add 367 mul 12 idiv add + y 4900 add mn add 100 idiv 3 mul 4 idiv sub + d add + 32075 sub + end +} bind def + +/test.start { + print (:) print + /test.pass 0 def + /test.count 0 def +} bind def + +/test { + /test.count test.count 1 add def + { + /test.pass test.pass 1 add def + } { + ( ) print + test.count (....) cvs print + (-fail) print + } ifelse +} bind def + + +% end included library code + +/daystogether { + 2 dict begin + /starts 2 array def + /ends 2 array def + dup 0 get s2jd starts exch 1 exch put + 1 get s2jd ends exch 1 exch put + dup 0 get s2jd starts exch 0 exch put + 1 get s2jd ends exch 0 exch put + starts quicksort + ends quicksort + ends 0 get starts 1 get ge { + ends 0 get starts 1 get sub 1 add + } { + 0 + } ifelse + end +} bind def + +/s2jd { + [ exch + 2022 exch + dup + 3 2 getinterval cvi exch + 0 2 getinterval cvi + ] + ymd2jd +} bind def + +(daystogether) test.start +[ (12-01) (20-01) ] [ (15-01) (18-01) ] daystogether 4 eq test +[ (02-03) (12-03) ] [ (13-03) (14-03) ] daystogether 0 eq test +[ (02-03) (12-03) ] [ (11-03) (15-03) ] daystogether 2 eq test +[ (30-03) (05-04) ] [ (28-03) (02-04) ] daystogether 4 eq test +test.end diff --git a/challenge-187/roger-bell-west/postscript/ch-2.ps b/challenge-187/roger-bell-west/postscript/ch-2.ps new file mode 100644 index 0000000000..b4f239de20 --- /dev/null +++ b/challenge-187/roger-bell-west/postscript/ch-2.ps @@ -0,0 +1,222 @@ +%!PS + +% begin included library code +% see https://github.com/Firedrake/postscript-libraries/ +/deepeq { + 2 dict begin + /a exch def + /b exch def + a type b type eq { + a type /dicttype eq { + a length b length eq { + << + a { + pop + true + } forall + b { + pop + true + } forall + >> + true exch + { + pop + dup a exch known { + dup b exch known { + dup a exch get exch b exch get deepeq not { + pop false + } if + } { + false + } ifelse + } { + false + } ifelse + } forall + } { + false + } ifelse + } { + a type dup /arraytype eq exch /stringtype eq or { + a length b length eq { + true + 0 1 a length 1 sub { + dup a exch get exch b exch get deepeq not { + pop false + exit + } if + } for + } { + false + } ifelse + } { + a b eq + } ifelse + } ifelse + } { + false + } ifelse + end +} bind def + +/quicksort { % [ a c b ] -> [ a b c ] + 1 dict begin + /arr exch def + arr length 0 gt { + 0 arr length 1 sub quicksort.main + } if + arr + end +} bind def + +/quicksort.partition { + 3 dict begin + /pivot arr hi lo add 2 idiv get def + /i lo 1 sub def + /j hi 1 add def + { + { + /i i 1 add def + arr i get pivot ge { + exit + } if + } loop + { + /j j 1 sub def + arr j get pivot le { + exit + } if + } loop + i j ge { + j + exit + } if + i j quicksort.swap + } loop + end +} bind def + +/quicksort.main { % lo hi -> (null) + 3 dict begin + /hi exch def + /lo exch def + /xit false def + lo 0 lt { + /xit true def + } if + hi 0 lt { + /xit true def + } if + lo hi ge { + /xit true def + } if + xit not { + /p quicksort.partition def + lo p quicksort.main + p 1 add hi quicksort.main + } if + end +} bind def + +/quicksort.swap { + 2 dict begin + /bi exch def + /ai exch def + arr ai get + arr bi get + arr exch ai exch put + arr exch bi exch put + end +} bind def + +/test.end { + ( ) print + test.count 0 gt { + (Passed ) print + test.pass (...) cvs print + (/) print + test.count (...) cvs print + ( \() print + test.pass 100 mul test.count idiv (...) cvs print + (%\)) print + (\r\n) print + } if +} bind def + +/test { + /test.count test.count 1 add def + { + /test.pass test.pass 1 add def + } { + ( ) print + test.count (....) cvs print + (-fail) print + } ifelse +} bind def + +/test.start { + print (:) print + /test.pass 0 def + /test.count 0 def +} bind def + + +% end included library code + +/reverse { + 3 dict begin + /str exch def + str length 0 gt { + /temp str 0 get def + /i 0 def + str length 2 idiv { + /temp str i get def + str i str str length i sub 1 sub get put + str str length i sub 1 sub temp put + /i i 1 add def + } repeat + } if + str + end +} bind def + +/magicaltriplets { + 6 dict begin + /a exch def + /out 0 array def + /mv 0 def + 0 + 1 + a length 3 sub { + /ai exch def + ai 1 add + 1 + a length 2 sub { + /bi exch def + bi 1 add + 1 + a length 1 sub { + /ci exch def + a ai get a bi get add a ci get gt + a bi get a ci get add a ai get gt and + a ai get a ci get add a bi get gt and { + /v a ai get a bi get add a ci get add def + v mv gt { + /mv v def + /out [ a ai get a bi get a ci get ] def + } if + } if + } for + } for + } for + out quicksort reverse + end +} bind def + +(magicaltriplets) test.start +[ 1 2 3 2 ] magicaltriplets [ 3 2 2 ] deepeq test +[ 1 3 2 ] magicaltriplets [ ] deepeq test +[ 1 1 2 3 ] magicaltriplets [ ] deepeq test +[ 2 4 3 ] magicaltriplets [ 4 3 2 ] deepeq test +test.end diff --git a/challenge-187/roger-bell-west/python/ch-1.py b/challenge-187/roger-bell-west/python/ch-1.py new file mode 100755 index 0000000000..b7be1cd5c4 --- /dev/null +++ b/challenge-187/roger-bell-west/python/ch-1.py @@ -0,0 +1,43 @@ +#! /usr/bin/python3 + +import unittest + +from datetime import date, timedelta +import re + +def s2date(ds): + dm = re.findall(r"\d+", ds) + if len(dm) == 2: + return date(2022, int(dm[1]), int(dm[0])) + +def daystogether(a, b): + starts = sorted([s2date(a[0]), s2date(b[0])]) + ends = sorted([s2date(a[1]), s2date(b[1])]) + if ends[0] >= starts[1]: + return (ends[0]-starts[1]).days+1 + else: + return 0 + +class TestDaystogether(unittest.TestCase): + + def test_ex1(self): + self.assertEqual(daystogether(["12-01", "20-01"], ["15-01", "18-01"]), + 4, + 'example 1') + + def test_ex2(self): + self.assertEqual(daystogether(["02-03", "12-03"], ["13-03", "14-03"]), + 0, + 'example 2') + + def test_ex3(self): + self.assertEqual(daystogether(["02-03", "12-03"], ["11-03", "15-03"]), + 2, + 'example 3') + + def test_ex4(self): + self.assertEqual(daystogether(["30-03", "05-04"], ["28-03", "02-04"]), + 4, + 'example 4') + +unittest.main() diff --git a/challenge-187/roger-bell-west/python/ch-2.py b/challenge-187/roger-bell-west/python/ch-2.py new file mode 100755 index 0000000000..0686ce96cd --- /dev/null +++ b/challenge-187/roger-bell-west/python/ch-2.py @@ -0,0 +1,40 @@ +#! /usr/bin/python3 + +import unittest + +from itertools import combinations + +def magicaltriplets(a): + out = [] + mv = 0 + for b in combinations(a, 3): + if b[0] + b[1] > b[2] and b[1] + b[2] > b[0] and b[0] + b[2] > b[1]: + v = sum(b) + if v > mv: + mv = v + out = b + return list(reversed(sorted(out))) + +class TestMagicaltriplets(unittest.TestCase): + + def test_ex1(self): + self.assertEqual(magicaltriplets([1, 2, 3, 2]), + [3, 2, 2], + 'example 1') + + def test_ex2(self): + self.assertEqual(magicaltriplets([1, 3, 2]), + [], + 'example 2') + + def test_ex3(self): + self.assertEqual(magicaltriplets([1, 1, 2, 3]), + [], + 'example 3') + + def test_ex4(self): + self.assertEqual(magicaltriplets([2, 4, 3]), + [4, 3, 2], + 'example 4') + +unittest.main() diff --git a/challenge-187/roger-bell-west/raku/ch-1.p6 b/challenge-187/roger-bell-west/raku/ch-1.p6 new file mode 100755 index 0000000000..f90728fc46 --- /dev/null +++ b/challenge-187/roger-bell-west/raku/ch-1.p6 @@ -0,0 +1,40 @@ +#! /usr/bin/perl6 + +use Test; + +plan 4; + +is-deeply(daystogether(["12-01", "20-01"], ["15-01", "18-01"]), + 4, + 'example 1'); + +is-deeply(daystogether(["02-03", "12-03"], ["13-03", "14-03"]), + 0, + 'example 2'); + +is-deeply(daystogether(["02-03", "12-03"], ["11-03", "15-03"]), + 2, + 'example 3'); + +is-deeply(daystogether(["30-03", "05-04"], ["28-03", "02-04"]), + 4, + 'example 4'); + +sub daystogether(@a,@b) { + my @starts = [s2date(@a[0]), s2date(@b[0])].sort; + my @ends = [s2date(@a[1]), s2date(@b[1])].sort; + if (@ends[0] > @starts[1]) { + return @ends[0]-@starts[1]+1; + } else { + return 0; + } +} + +sub s2date($ds) { + if ($ds ~~ /^(\d+)\-(\d+)$/) { + return Date.new(year => 2022, + month => $1, + day => $0); + } + die "$ds is not a recognisable date\n"; +} diff --git a/challenge-187/roger-bell-west/raku/ch-2.p6 b/challenge-187/roger-bell-west/raku/ch-2.p6 new file mode 100755 index 0000000000..805ed2f684 --- /dev/null +++ b/challenge-187/roger-bell-west/raku/ch-2.p6 @@ -0,0 +1,38 @@ +#! /usr/bin/perl6 + +use Test; + +plan 4; + +is-deeply(magicaltriplets([1, 2, 3, 2]), + [3, 2, 2], + 'example 1'); + +is-deeply(magicaltriplets([1, 3, 2]), + [], + 'example 2'); + +is-deeply(magicaltriplets([1, 1, 2, 3]), + [], + 'example 3'); + +is-deeply(magicaltriplets([2, 4, 3]), + [4, 3, 2], + 'example 4'); + +sub magicaltriplets(@a) { + my @out; + my $mv = 0; + for @a.combinations(3) -> @b { + if (@b[0] + @b[1] > @b[2] && + @b[1] + @b[2] > @b[0] && + @b[0] + @b[2] > @b[1]) { + my $v = @b.sum; + if ($v > $mv) { + $mv = $v; + @out = @b; + } + } + } + return Array(@out.sort.reverse); +} diff --git a/challenge-187/roger-bell-west/ruby/ch-1.rb b/challenge-187/roger-bell-west/ruby/ch-1.rb new file mode 100755 index 0000000000..fa83e9dad2 --- /dev/null +++ b/challenge-187/roger-bell-west/ruby/ch-1.rb @@ -0,0 +1,44 @@ +#! /usr/bin/ruby + +require 'test/unit' + +require 'time' + +def s2date(ds) + /^(\d+)\-(\d+)$/ =~ ds + return Time.new(2022, $2, $1, 0, 0, 0, "+0000") +end + +def daystogether(a, b) + starts = [s2date(a[0]), s2date(b[0])].sort + ends = [s2date(a[1]), s2date(b[1])].sort + if ends[0] >= starts[1] then + return (ends[0]-starts[1]).to_i/86400+1 + else + return 0 + end +end + +class TestDaystogether < Test::Unit::TestCase + + def test_ex1 + assert_equal(4, + daystogether(["12-01", "20-01"], ["15-01", "18-01"])) + end + + def test_ex2 + assert_equal(0, + daystogether(["02-03", "12-03"], ["13-03", "14-03"])) + end + + def test_ex3 + assert_equal(2, + daystogether(["02-03", "12-03"], ["11-03", "15-03"])) + end + + def test_ex4 + assert_equal(4, + daystogether(["30-03", "05-04"], ["28-03", "02-04"])) + end + +end diff --git a/challenge-187/roger-bell-west/ruby/ch-2.rb b/challenge-187/roger-bell-west/ruby/ch-2.rb new file mode 100755 index 0000000000..3d557c79bf --- /dev/null +++ b/challenge-187/roger-bell-west/ruby/ch-2.rb @@ -0,0 +1,44 @@ +#! /usr/bin/ruby + +require 'test/unit' + +def magicaltriplets(a) + out = [] + mv = 0 + a.combination(3) do |b| + if b[0] + b[1] > b[2] && + b[1] + b[2] > b[0] && + b[0] + b[2] > b[1] then + v = b[0] + b[1] + b[2] + if v > mv then + mv = v + out = b + end + end + end + return out.sort.reverse +end + +class TestMagicaltriplets < Test::Unit::TestCase + + def test_ex1 + assert_equal([3, 2, 2], + magicaltriplets([1, 2, 3, 2])) + end + + def test_ex2 + assert_equal([], + magicaltriplets([1, 3, 2])) + end + + def test_ex3 + assert_equal([], + magicaltriplets([1, 1, 2, 3])) + end + + def test_ex4 + assert_equal([4, 3, 2], + magicaltriplets([2, 4, 3])) + end + +end diff --git a/challenge-187/roger-bell-west/rust/ch-1.rs b/challenge-187/roger-bell-west/rust/ch-1.rs new file mode 100644 index 0000000000..50fa92c23a --- /dev/null +++ b/challenge-187/roger-bell-west/rust/ch-1.rs @@ -0,0 +1,40 @@ +// [dependencies] +// chrono = "0.4.19" + +use chrono::NaiveDate; + +#[test] +fn text_ex1() { + assert_eq!(daystogether(["12-01", "20-01"], ["15-01", "18-01"]), 4); +} + +#[test] +fn text_ex2() { + assert_eq!(daystogether(["02-03", "12-03"], ["13-03", "14-03"]), 0); +} + +#[test] +fn text_ex3() { + assert_eq!(daystogether(["02-03", "12-03"], ["11-03", "15-03"]), 2); +} + +#[test] +fn text_ex4() { + assert_eq!(daystogether(["30-03", "05-04"], ["28-03", "02-04"]), 4); +} + +fn s2date(ds: &str) -> NaiveDate { + NaiveDate::parse_from_str(&(ds.to_owned() + "-2022"), "%d-%m-%Y").unwrap() +} + +fn daystogether(a: [&str; 2], b: [&str; 2]) -> usize { + let mut starts = vec![s2date(a[0]), s2date(b[0])]; + starts.sort(); + let mut ends = vec![s2date(a[1]), s2date(b[1])]; + ends.sort(); + if ends[0] >= starts[1] { + (ends[0] - starts[1]).num_days() as usize + 1 + } else { + 0 + } +} diff --git a/challenge-187/roger-bell-west/rust/ch-2.rs b/challenge-187/roger-bell-west/rust/ch-2.rs new file mode 100644 index 0000000000..e27b817625 --- /dev/null +++ b/challenge-187/roger-bell-west/rust/ch-2.rs @@ -0,0 +1,41 @@ +// [dependencies] +// itertools = "0.10.5" + +use itertools::Itertools; + +#[test] +fn test_ex1() { + assert_eq!(magicaltriplets(vec![1, 2, 3, 2]), vec![3, 2, 2]); +} + +#[test] +fn test_ex2() { + assert_eq!(magicaltriplets(vec![1, 3, 2]), vec![]); +} + +#[test] +fn test_ex3() { + assert_eq!(magicaltriplets(vec![1, 1, 2, 3]), vec![]); +} + +#[test] +fn test_ex4() { + assert_eq!(magicaltriplets(vec![2, 4, 3]), vec![4, 3, 2]); +} + +fn magicaltriplets(a: Vec) -> Vec { + let mut out: Vec = Vec::new(); + let mut mv = 0; + for b in a.iter().combinations(3) { + if b[0] + b[1] > *b[2] && b[1] + b[2] > *b[0] && b[0] + b[2] > *b[1] { + let v = b[0] + b[1] + b[2]; + if v > mv { + mv = v; + out = b.iter().map(|i| **i).collect::>(); + } + } + } + out.sort(); + out.reverse(); + out +} -- cgit From f50a1e5e7dd6a30f1a63732a76e277a57260c142 Mon Sep 17 00:00:00 2001 From: Luca Ferrari Date: Mon, 17 Oct 2022 12:14:24 +0200 Subject: Task 1 and 2 PLPerl --- challenge-187/luca-ferrari/postgresql/ch-1.plperl | 45 ++++++++++++++++++++ challenge-187/luca-ferrari/postgresql/ch-2.plperl | 51 +++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 challenge-187/luca-ferrari/postgresql/ch-1.plperl create mode 100644 challenge-187/luca-ferrari/postgresql/ch-2.plperl diff --git a/challenge-187/luca-ferrari/postgresql/ch-1.plperl b/challenge-187/luca-ferrari/postgresql/ch-1.plperl new file mode 100644 index 0000000000..b4f2b0f93b --- /dev/null +++ b/challenge-187/luca-ferrari/postgresql/ch-1.plperl @@ -0,0 +1,45 @@ +-- Perl Weekly Challenge 187 +-- Task 1 + +CREATE SCHEMA IF NOT EXISTS pwc187; + +CREATE OR REPLACE FUNCTION +pwc187.task1_plperl( text, text, text, text ) +RETURNS INT +AS $CODE$ +use DateTime; +my ( $foo_start, $foo_end, $bar_start, $bar_end ) = @_; +my @dates; + +for ( $foo_start, $foo_end, $bar_start, $bar_end ) { + $_ =~ / ^ (\d{2}) - (\d{2}) $ /x; + push @dates, DateTime->new( year => 2022, day => $1, month => $2 ); +} + +my $days = 0; + +if ( DateTime->compare( $dates[ 0 ], $dates[ 3 ] ) > 0 + || DateTime->compare( $dates[ 1 ], $dates[ 2 ] ) < 0 ) { + # one ends before the begin of the other or viceversa + $days = 0; +} +else { + my ( $start, $end ); + $start = DateTime->compare( $dates[ 0 ], $dates[ 2 ] ) <= 0 ? $dates[ 0 ] : $dates[ 2 ]; + $end = DateTime->compare( $dates[ 1 ], $dates[ 3 ] ) <= 0 ? $dates[ 1 ] : $dates[ 3 ]; + + while ( DateTime->compare( $start, $end ) <= 0 ) { + $days++ if ( DateTime->compare( $start, $dates[ 0 ] ) >= 0 + && DateTime->compare( $start, $dates[ 1 ] ) <= 0 + && DateTime->compare( $start, $dates[ 2 ] ) >= 0 + && DateTime->compare( $start, $dates[ 3 ] ) <= 0 ); + $start = $start->add( days => 1 ); + } +} + + + +return $days; + +$CODE$ +LANGUAGE plperlu; diff --git a/challenge-187/luca-ferrari/postgresql/ch-2.plperl b/challenge-187/luca-ferrari/postgresql/ch-2.plperl new file mode 100644 i