aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbigail <abigail@abigail.be>2021-11-03 17:41:34 +0100
committerAbigail <abigail@abigail.be>2021-11-03 17:41:34 +0100
commit172d3d442f2e84abb4a29454124d00d50cdae72a (patch)
tree3dc6b1687d379f28f76677b262220d93b1b38af4
parent1b32e48dbd84df6f39012c6c90e2b809df190e3b (diff)
downloadperlweeklychallenge-club-172d3d442f2e84abb4a29454124d00d50cdae72a.tar.gz
perlweeklychallenge-club-172d3d442f2e84abb4a29454124d00d50cdae72a.tar.bz2
perlweeklychallenge-club-172d3d442f2e84abb4a29454124d00d50cdae72a.zip
Alternative Perl solution for week 137, part 1
-rw-r--r--challenge-137/abigail/README.md4
-rw-r--r--challenge-137/abigail/perl/ch-1.pl7
-rw-r--r--challenge-137/abigail/perl/ch-1a.pl68
3 files changed, 75 insertions, 4 deletions
diff --git a/challenge-137/abigail/README.md b/challenge-137/abigail/README.md
index 0707d1fbd5..49fca86bcd 100644
--- a/challenge-137/abigail/README.md
+++ b/challenge-137/abigail/README.md
@@ -11,7 +11,9 @@
* [Lua](lua/ch-1.lua)
* [Node.js](node/ch-1.js)
* [Pascal](pascal/ch-1.p)
-* [Perl](perl/ch-1.pl)
+* Perl
+ * [Using loop-up](perl/ch-1.pl)
+ * [Using Doomsday values](perl/ch-1a.pl)
* [Python](python/ch-1.py)
* [R](r/ch-1.r)
* [Ruby](ruby/ch-1.rb)
diff --git a/challenge-137/abigail/perl/ch-1.pl b/challenge-137/abigail/perl/ch-1.pl
index 875aca99a4..72e0efe0b4 100644
--- a/challenge-137/abigail/perl/ch-1.pl
+++ b/challenge-137/abigail/perl/ch-1.pl
@@ -36,15 +36,16 @@ use experimental 'lexical_subs';
#
# Now, we could calculate the day of the week of Jan 1 and Dec 31,
# either using a module or some handrolled calculations, checking
-# whether at least of those days is a Thursday.
+# whether at least of those days is a Thursday.
#
# Or we could just list the 71 years in a 400 year period, and so
# some trivial arithmetic.
#
-# Guess which method we're using.
+# We opt to use the latter method in this solution.
+# For the former method, see ch-1a.pl.
#
-my @start_years = qw [1600 2000]
+my @start_years = qw [1600 2000];
my @long_year_offsets = qw [
004 009 015 020 026
032 037 043 048 054
diff --git a/challenge-137/abigail/perl/ch-1a.pl b/challenge-137/abigail/perl/ch-1a.pl
new file mode 100644
index 0000000000..32d5f82a0b
--- /dev/null
+++ b/challenge-137/abigail/perl/ch-1a.pl
@@ -0,0 +1,68 @@
+#!/opt/perl/bin/perl
+
+use 5.032;
+
+use strict;
+use warnings;
+no warnings 'syntax';
+
+use experimental 'signatures';
+use experimental 'lexical_subs';
+
+#
+# See ../README.md
+#
+
+#
+# Run as: perl ch-1a.pl
+#
+
+#
+# A year is a long year if the last day of the year is a Thursday,
+# or if the last day of the year is a Friday, and the year is a
+# leap year.
+#
+# To determine the day of the week of Dec 31, we first calculate the
+# Doomsday value of the year: this is the day of the week of 4/4,
+# 6/6, 8/8, 10/10, 12/12, 5/9, 9/5, 7/11, 11/7, Pi day, the last
+# day of February, and January 3 (non leap years) or January 4 (leap years)
+#
+# Given the day of the week of Dec 12, it's trivial to calculate the
+# day of the week of Dec 31.
+#
+# See also ch-1.pl for an alternative method to solve this.
+#
+
+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)
+}
+
+foreach my $year (1900 .. 2100) {
+ #
+ # Get the Doomsday value; this is the day of the week of December 12.
+ # Add 31, subtract 12 to get the day of the week of Dec 31.
+ #
+ my $doomsday = doomsday ($year);
+ my $dec_31 = ($doomsday - 12 + 31) % 7;
+ say $year if $dec_31 == $THURSDAY || $dec_31 == $FRIDAY && is_leap $year;
+}