aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbigail <abigail@abigail.be>2021-11-08 23:44:00 +0100
committerAbigail <abigail@abigail.be>2021-11-08 23:44:48 +0100
commit8ac7ce4cd04ee377060f1d73f5169b680bfba190 (patch)
treec70e14410d1c431c4d7bc7fbf06d3f45e3f99192
parent05958e021f9a1368c83dbfe0b76c387d481f7fb6 (diff)
downloadperlweeklychallenge-club-8ac7ce4cd04ee377060f1d73f5169b680bfba190.tar.gz
perlweeklychallenge-club-8ac7ce4cd04ee377060f1d73f5169b680bfba190.tar.bz2
perlweeklychallenge-club-8ac7ce4cd04ee377060f1d73f5169b680bfba190.zip
Perl solution for week 138, part 1
-rw-r--r--challenge-138/abigail/perl/ch-1.pl89
1 files changed, 89 insertions, 0 deletions
diff --git a/challenge-138/abigail/perl/ch-1.pl b/challenge-138/abigail/perl/ch-1.pl
new file mode 100644
index 0000000000..eae1bea355
--- /dev/null
+++ b/challenge-138/abigail/perl/ch-1.pl
@@ -0,0 +1,89 @@
+#!/opt/perl/bin/perl
+
+use 5.028;
+
+use strict;
+use warnings;
+no warnings 'syntax';
+
+use experimental 'signatures';
+use experimental 'lexical_subs';
+
+#
+# See ../README.md
+#
+
+#
+# Run as: perl ch-1.pl < input-file
+#
+
+#
+# A year can have 260, 261 or 262 workdays.
+#
+# Regular years start and end on the same day of the week. Which means
+# that if Jan 1 is a workday, then Dec 31 is, and hence, the year has
+# 261 workdays. If Jan 1 is a weekday, the year has 260 workdays.
+#
+# Leap years ends on a day which is one day later than the day of the
+# week it starts on. So, if Jan 1 is Monday to Thursday, the year ends
+# on a Tuesday to Friday, resulting in a year with 262 workdays. If the
+# year starts on a Friday, it ends on a Saturday, giving 261 workdays.
+# If the year starts on a Saturday, it ends on a Sunday, giving 260 workdays,
+# and if the year starts on a Sunday, it ends on a Monday, giving 261
+# workdays.
+#
+# So, we could make a lookup table, based on the day of the week of
+# Jan 1, and whether the year is a leap day or not. But we won't. Since
+# last weeks challenge made us calculate the Doomsday value of the year,
+# we will make a lookup table based on that. The Doomsday value is the
+# day of the week on Jan 3 (regular years), or Jan 4 (leap years).
+#
+# This gives us the following table:
+#
+# +-------+----------+-------+----------+
+# | Regular Year | Leap Year |
+# +----------------+-------+----------+-------+----------+
+# | Doomsday value | Jan 1 | Workdays | Jan 1 | Workdays |
+# +----------------+-------+----------+-------+----------+
+# | 0 | Thu | 261 | Wed | 262 |
+# | 1 | Fri | 261 | Thu | 262 |
+# | 2 | Sat | 260 | Fri | 261 |
+# | 3 | Sun | 260 | Sat | 260 |
+# | 4 | Mon | 261 | Sun | 261 |
+# | 5 | Tue | 261 | Mon | 262 |
+# | 6 | Wed | 261 | Tue | 262 |
+# +----------------+-------+----------+-------+----------+
+
+my @lookup = (
+ [261, 261, 260, 260, 261, 261, 261], # Regular years
+ [262, 262, 261, 260, 261, 262, 262], # Leap years
+);
+
+my $SUNDAY = 0;
+my $MONDAY = 1;
+my $TUESDAY = 2;
+my $WEDNESDAY = 3;
+my $THURSDAY = 4;
+my $FRIDAY = 5;
+my $SATURDAY = 6;
+
+#
+# Given a year, return its "Doomsday" value.
+# 0 -> Sunday, 6 -> Saturday
+#
+sub doomsday ($year) {
+ use integer;
+ my $anchor = ($TUESDAY, $SUNDAY, $FRIDAY, $WEDNESDAY) [($year / 100) % 4];
+ my $y = $year % 100;
+ my $doomsday = ((($y / 12) + ($y % 12) + (($y % 12) / 4)) + $anchor) % 7;
+ $doomsday;
+}
+
+sub is_leap ($year) {
+ ($year % 400 == 0) || ($year % 4 == 0) && ($year % 100 != 0) ? 1 : 0
+}
+
+
+while (<>) {
+ say $lookup [is_leap $_] [doomsday $_]
+}