aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbigail <abigail@abigail.be>2021-11-11 18:30:20 +0100
committerAbigail <abigail@abigail.be>2021-11-11 18:30:20 +0100
commit14510de14e1f435b1439c451a2fa5cb9971a7c78 (patch)
tree6e48ef1b03a8b4d80319960f7f3bd14d2bad3975
parent63c89ec61dbd7965ab5403340dae7fe36441592c (diff)
parent04bf8a1351c8d90860e2d5865779d85db3c60f50 (diff)
downloadperlweeklychallenge-club-14510de14e1f435b1439c451a2fa5cb9971a7c78.tar.gz
perlweeklychallenge-club-14510de14e1f435b1439c451a2fa5cb9971a7c78.tar.bz2
perlweeklychallenge-club-14510de14e1f435b1439c451a2fa5cb9971a7c78.zip
Merge branch 'abigail/week-138' of github.com:Abigail/perlweeklychallenge-club into abigail/week-138
-rw-r--r--challenge-138/abigail/perl/ch-1.pl89
-rw-r--r--challenge-138/abigail/perl/ch-2.pl63
-rw-r--r--challenge-138/abigail/t/ctest.ini8
-rw-r--r--challenge-138/abigail/t/input-1-12
-rw-r--r--challenge-138/abigail/t/input-2-13
-rw-r--r--challenge-138/abigail/t/output-1-1.exp2
-rw-r--r--challenge-138/abigail/t/output-2-1.exp3
7 files changed, 170 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 $_]
+}
diff --git a/challenge-138/abigail/perl/ch-2.pl b/challenge-138/abigail/perl/ch-2.pl
new file mode 100644
index 0000000000..b9169688ee
--- /dev/null
+++ b/challenge-138/abigail/perl/ch-2.pl
@@ -0,0 +1,63 @@
+#!/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-2.pl < input-file
+#
+
+#
+# We solve this with a recursive function. "can_split" gets two arguments,
+# '$target', the number we have to achieve as a sum of parts, and
+# '$number', the number we have to split into parts.
+#
+# If $target exceeds $number, we return 0, as we cannot split a number into
+# parts and have it sum to something larger.
+# If $target equals $number, we return 1, as we can trivial fulfill this.
+#
+# Else, we take ever larger parts from the end, subtract that part from
+# $target, and recurse. If no part succeeds, we have a failure. If any
+# part succeeds, we have a winner.
+#
+# Note that the only two numbers where the sqrt is equal to itself are
+# 0 and 1 -- we have to exclude those as we need to split the original
+# number into at least two parts. For all other numbers, its square root
+# will be less, so not splitting the original number can't sum to the
+# square root.
+#
+
+sub can_split ($target, $number) {
+ return 0 if $target > $number || $target < 0;
+ return 1 if $target == $number;
+
+ my $pow_10 = 10;
+ #
+ # We could use substring instead of modolu and division, but modulo
+ # and division we can trivially port to other language solutions,
+ # while taking substrings requires more work.
+ #
+ while ($pow_10 < $number) {
+ use integer;
+ return 1 if can_split ($target - ($number % $pow_10),
+ $number / $pow_10);
+ $pow_10 *= 10;
+ }
+
+ return 0;
+}
+
+while (<>) {
+ chomp;
+ say $_ > 1 && can_split (sqrt ($_), $_) ? 1 : 0
+}
diff --git a/challenge-138/abigail/t/ctest.ini b/challenge-138/abigail/t/ctest.ini
new file mode 100644
index 0000000000..527781acbb
--- /dev/null
+++ b/challenge-138/abigail/t/ctest.ini
@@ -0,0 +1,8 @@
+#
+# Configuration file for running tests, using ctest.
+# See https://github.com/Abigail/Misc/blob/master/ctest
+#
+
+[names]
+1-1 = Given Examples
+2-1 = Given Examples
diff --git a/challenge-138/abigail/t/input-1-1 b/challenge-138/abigail/t/input-1-1
new file mode 100644
index 0000000000..bedf748f35
--- /dev/null
+++ b/challenge-138/abigail/t/input-1-1
@@ -0,0 +1,2 @@
+2021
+2020
diff --git a/challenge-138/abigail/t/input-2-1 b/challenge-138/abigail/t/input-2-1
new file mode 100644
index 0000000000..e388b97ecb
--- /dev/null
+++ b/challenge-138/abigail/t/input-2-1
@@ -0,0 +1,3 @@
+81
+9801
+36
diff --git a/challenge-138/abigail/t/output-1-1.exp b/challenge-138/abigail/t/output-1-1.exp
new file mode 100644
index 0000000000..dc9667c339
--- /dev/null
+++ b/challenge-138/abigail/t/output-1-1.exp
@@ -0,0 +1,2 @@
+261
+262
diff --git a/challenge-138/abigail/t/output-2-1.exp b/challenge-138/abigail/t/output-2-1.exp
new file mode 100644
index 0000000000..2f1465d159
--- /dev/null
+++ b/challenge-138/abigail/t/output-2-1.exp
@@ -0,0 +1,3 @@
+1
+1
+0