diff options
| -rwxr-xr-x | challenge-237/e-choroba/perl/ch-1.pl | 59 | ||||
| -rwxr-xr-x | challenge-237/e-choroba/perl/ch-2.pl | 63 |
2 files changed, 122 insertions, 0 deletions
diff --git a/challenge-237/e-choroba/perl/ch-1.pl b/challenge-237/e-choroba/perl/ch-1.pl new file mode 100755 index 0000000000..4d53d02709 --- /dev/null +++ b/challenge-237/e-choroba/perl/ch-1.pl @@ -0,0 +1,59 @@ +#!/usr/bin/perl +use warnings; +use strict; +use experimental qw( signatures ); + +use Time::Piece; +use Time::Seconds qw{ ONE_DAY ONE_WEEK }; + +sub seize_the_day($year, $month, $weekday_of_month, $day_of_week) { + return 0 if $weekday_of_month > 5; + + # In the input, 1 is Monday, 7 is Sunday. + $day_of_week = ((1 + $day_of_week) % 7) || 7; + + my $tp = 'Time::Piece'->strptime(sprintf('%04d%02d%02d', $year, $month, 1), + '%Y%m%d'); + my $weekday = $tp->wday; + $tp += ONE_DAY * (($day_of_week - $weekday) % 7); # The expected weekday. + $tp += ONE_WEEK * ($weekday_of_month - 1); # The expected week. + return $tp->mon == $month ? $tp->mday : 0 +} + +use Test::More tests => 3 + 26; + +is seize_the_day(2024, 4, 3, 2), 16, + 'Example 1 # The 3rd Tue of Apr 2024 is the 16th'; +is seize_the_day(2025, 10, 2, 4), 9, + 'Example 2 # The 2nd Thu of Oct 2025 is the 9th'; +is seize_the_day(2026, 8, 5, 3), 0, + "Example 3 # There isn't a 5th Wed in Aug 2026"; + +is seize_the_day(2023, 1, 53, 1), 0, '53 weeks in a year'; + +is seize_the_day(2023, 10, 1, 1), 2, 'Mon Oct 2 2023'; +is seize_the_day(2023, 10, 1, 2), 3, 'Tue Oct 3 2023'; +is seize_the_day(2023, 10, 1, 3), 4, 'Tue Oct 4 2023'; +is seize_the_day(2023, 10, 1, 4), 5, 'Tue Oct 5 2023'; +is seize_the_day(2023, 10, 1, 5), 6, 'Tue Oct 6 2023'; +is seize_the_day(2023, 10, 1, 6), 7, 'Tue Oct 7 2023'; +is seize_the_day(2023, 10, 1, 7), 1, 'Sun Oct 1 2023'; +is seize_the_day(2023, 10, 2, 1), 9, 'Mon Oct 9 2023'; +is seize_the_day(2023, 10, 2, 7), 8, 'Sun Oct 8 2023'; +is seize_the_day(2023, 10, 5, 1), 30, 'Mon Oct 30 2023'; +is seize_the_day(2023, 10, 5, 2), 31, 'Tue Oct 31 2023'; +is seize_the_day(2023, 10, 5, 7), 29, 'Sun Oct 29 2023'; + +is seize_the_day(2023, 12, 1, 1), 4, 'Mon Dec 4 2023'; +is seize_the_day(2023, 12, 1, 2), 5, 'Tue Dec 5 2023'; +is seize_the_day(2023, 12, 1, 3), 6, 'Wed Dec 6 2023'; +is seize_the_day(2023, 12, 1, 4), 7, 'Thu Dec 7 2023'; +is seize_the_day(2023, 12, 1, 5), 1, 'Fri Dec 1 2023'; +is seize_the_day(2023, 12, 1, 6), 2, 'Sat Dec 2 2023'; +is seize_the_day(2023, 12, 1, 7), 3, 'Sun Dec 3 2023'; +is seize_the_day(2023, 12, 2, 1), 11, 'Mon Dec 11 2023'; +is seize_the_day(2023, 12, 2, 5), 8, 'Fri Dec 8 2023'; +is seize_the_day(2023, 12, 4, 4), 28, 'Thu Dec 28 2023'; +is seize_the_day(2023, 12, 5, 6), 30, 'Sat Dec 30 2023'; +is seize_the_day(2023, 12, 5, 7), 31, 'Sun Dec 31 2023'; +is seize_the_day(2023, 12, 5, 1), 0, '4 Mondays in Dec 2023'; diff --git a/challenge-237/e-choroba/perl/ch-2.pl b/challenge-237/e-choroba/perl/ch-2.pl new file mode 100755 index 0000000000..80c6e835c2 --- /dev/null +++ b/challenge-237/e-choroba/perl/ch-2.pl @@ -0,0 +1,63 @@ +#!/usr/bin/perl +use warnings; +use strict; +use experimental qw( signatures ); + +sub maximise_greatness(@nums) { + my @sorted = sort { $a <=> $b } @nums; + + # No greatness at all. + return 0 if $sorted[0] == $sorted[-1]; + + my $count = 0; + my $less = 0; + my $greater = 1; + while (1) { + ++$greater while $greater <= $#sorted + && $sorted[$greater] == $sorted[$less]; + last if $greater > $#sorted; + + ++$count if $sorted[$less++] < $sorted[$greater++]; + last if $greater > $#sorted; + } + return $count +} + +use Algorithm::Combinatorics qw{ permutations }; +sub maximise_greatness_brute_force(@nums) { + my $iter = permutations(\@nums); + my $max_count = 0; + while (my $p = $iter->next) { + my $count = grep $nums[$_] < $p->[$_], 0 .. $#nums; + $max_count = $count if $count > $max_count; + } + return $max_count +} + +use Test::More tests => 2 * (2 + 4) + 1; + +for my $maximise_greatness ( + \&maximise_greatness, \&maximise_greatness_brute_force +) { + + is $maximise_greatness->(1, 3, 5, 2, 1, 3, 1), 4, 'Example 1'; + is $maximise_greatness->(1, 2, 3, 4), 3, 'Example 2'; + + is $maximise_greatness->(1, 1, 1), 0, 'Not great'; + is $maximise_greatness->(1, 1, 2, 2, 2), 2, 'More of the greater ones'; + is $maximise_greatness->(1, 1, 1, 2, 2), 2, 'More of the less ones'; + is $maximise_greatness->(1, 2, 2, 2, 3), 2, 'More of the middle ones'; +} + +use Benchmark qw{ cmpthese }; +my @l = map int rand 7, 1 .. 8; +is maximise_greatness(@l), maximise_greatness_brute_force(@l), "same @l"; +cmpthese(-3, { + brute_force => sub { maximise_greatness_brute_force(@l) }, + optimised => sub { maximise_greatness(@l) }, +}); + +__END__ + Rate brute_force optimised +brute_force 8.74/s -- -100% +optimised 210776/s 2412117% -- |
