aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xchallenge-237/e-choroba/perl/ch-1.pl59
-rwxr-xr-xchallenge-237/e-choroba/perl/ch-2.pl63
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% --