######################################################################
Mindcal 0.01
######################################################################
NAME
Mindcal - Calculate day-of-week of any given date in your head
SYNOPSIS
use Mindcal;
use DateTime;
my $mc = Mindcal->new(
date => DateTime->new(
day => 1,
month => 1,
year => 2000,
)
);
print "Year item: ", $mc->year_item(), "\n";
print "Month item: ", $mc->month_item(), "\n";
print "Day item: ", $mc->day_item(), "\n";
print "Adjust: ", $mc->adjust(), "\n";
print "Weekday: ", $mc->weekday(), "\n";
DESCRIPTION
This module helps training the necessary mental steps to determine the
day of the week of any given date in your head.
The method was invented by Lewis Carroll ("Alice in Wonderland") and
eloquently described as hack #43 in "Mind Performance Hacks" by Ron
Hale-Evans, O'Reilly 2006.
The method involves calculating four different values of a given date in
your head, the year item, the month item, the day item and an
adjustment. Once you've calculated those four values, simply add them up
and calculate the remainder of a division by seven (so that's modulo 7)
and look up the day of the week in the following table:
0 Sunday
1 Monday
2 Tuesday
3 Wednesday
4 Thursday
5 Friday
6 Saturday
The Year Item
The year item can be determined by the following formula:
(YY + (YY div 4)) mod 7
YY is the two-digit year, the century gets discarded. YY of 2007 is
simply 07.
The 'div' operator is an ordinary division but it drops the remainder.
In this way, "7 div 4" is 1. Why? 7/4 results in 1, remainder 3, which
gets discarded.
The 'mod' operator is a modulo operation, which is the remainder after
an ordinary division. "7 mod 4" is 3. Why? 7/4 results in 1, remainder
3. Only the remainder is kept.
So, according to the formula above, the year item for the year 2007 is
(7 + (7 div 4)) mod 7
which is
(7 + 1) mod 7
and therefore 1.
The Month Item
The month items are best memorized as a string of numbers:
01 02 03 04 05 06 07 08 09 10 11 12
0 3 3 6 1 4 6 2 5 0 3 5
I personally memorize them as
* Start with "033".
* Continue with "614" (like 314, which is PI, just start with 6)
* Continue with "625" (that's 25*25, the area of a rectangle, as
opposed to a circle, as suggested by the previously used PI)
* End with "035" (that's two more than the start sequence "033")
It takes some practice to memorize these 12 numbers, but I've found that
it's quite easy to do if you split it up in two groups of 6 and map the
desired month number onto the correct group of 6.
To calculate the month item, look it up in the table above. For example,
the month item for July is 6.
The Day Item
The day item is simply the day of the month. For example, the day item
for July 27th is 27.
The Adjustment
The adjustment is dependent on the century and if the given year is a
leap year or not. For beginners, I recommend only memorizing the
following numbers:
1900 0
2000 6
So for a date between 1900 and 1999, the adjustment value is 0. Between
2000 and 2099, it is 6.
If the given year is a leap year and the given date is in January or
February, subtract 1 from the adjustment value. For example, if you want
to calculate the weekday of 1/1/2000 and you know that 2000 is a leap
year, the adjustment value is 5. Why? For 2000, according to the table
above, we have to add 6, but since it's a date in January of a leap
year, we subtract 1.
For more advanced users, here's the table for additional centuries:
1700 4
1800 2
1900 0
2000 6
2100 4
2200 2
2300 0
Adding it all up
After adding the year, month, day values and the adjustment, determine
the remainder after a division by 7 (in math terms, the result of a
modulo 7 operation).
For example, to determine the weekday of 11/27/1964, we calculate
* a year item of 3
* a month item of 3
* a day item of 27
* an adjustment of 0
Adding 3+3+27 yields 33, which has a remainder of 5 after a division by
7 (28 is the next-lowest number divisible by 7 and 33-28=5).
Looking up 5 in the weekday table yields a Friday. Therefore, 11/27/1964
is a Friday.
EXAMPLES
Let's train calculating year items on random years between 1900 and
2099:
use Mindcal;
use DateTime;
while(1) {
my $year = 1900 + int rand 200;
print "$year?\n";
<>;
my $mc = Mindcal->new(
date => DateTime->new(
day => 1,
month => 1,
year => $year,
)
);
print "Year item: ", $mc->year_item(), "\n";
}
For a script printing random dates and, on a push of a button, the
corresponding year, month, day, and adjustment values, try "mindcal"
which comes with the Mindcal CPAN distribution.
AUTHOR
Mike Schilli,
COPYRIGHT AND LICENSE
Copyright (C) 2007 by Mike Schilli
This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, either Perl version 5.8.5 or, at
your option, any later version of Perl 5 you may have available.