22.02.2013

perl gegen einen Facebook-Hoax

Auf Facebook und sicherlich auch an anderen Stellen kursiert derzeit ein Gerücht, dass angeblich eine bestimmte Konstellation von Wochentagen nur alle 823 Jahre vorkommt und man deshalb irgendetwas Abergläubisches tun müsste.

Genauer gesagt: es geht darum, dass angeblich das Auftreten von fünf kompletten Wochenenden (also Freitag, Samstag, Sonntag) in einem Kalendermonat extrem selten sein soll.

Klingt erstmal plausibel: die Woche hat sieben Tage, der Monat zwischen 28 und 31, wie häufig kann es also sein, dass fünf vollständige Wochenenden in so wenig Zeit passen? Gefühlt also extrem selten, und deshalb sind die meisten Leute gern gutgläubig und nehmen diese Behauptung für bare Münze, ohne selbst darüber nochmal nachzudenken.

Nehmen wir die Behauptung mal auseinander: damit in einen Monat wirklich fünf Wochenenden passen, muss der letzte Sonntag offensichtlich der 31. sein. In kürzeren Monaten mit 30, 29 oder 28 Tagen ist das nicht möglich.

Wenn also Sonntag der 31. ist, ist automatisch der 3. ein Sonntag (minus 28) und der 1. muss ein Freitag sein.

Was macht ein Informatiker nun? Er hackt sich ein kleines Programm zusammen, um mit brutaler Gewalt (wenn man aus der Fachsprache das "brute force" übersetzt) alle Möglichkeiten durchzuprobieren. Es reicht also, alle Monate mit 31 Tagen zu untersuchen, ob der 1. ein Freitag ist. Falls ja, haben wir einen solchen Treffer gefunden.

Hier ist ein solches Programm in der Skriptsprache perl, mal eben auf die Schnelle zusammen"gekloppt", um zu gegebenem Intervall (Anfangs- und Endejahr) alle Monate zu finden, auf die diese Bedingung zutrifft.

#!/usr/bin/perl -w
use POSIX;
my ($y,$m,$d);
# liste der monate mit 31 tagen
my @monate=(1,3,5,7,8,10,12);
# finde monate mit 5 vollen wochenenden
# das sind alle monate mit freitag als 1. und 31 tage
my ($anfang,$ende)=@ARGV;
$anfang=2000 unless ($anfang);
$ende=2019 unless ($ende);
# schleife fuer jahre
for ($y=$anfang; $y<$ende; ++$y) {
# schleife fuer monate
foreach $m (@monate) {
# unix timestamp fuer den 1. des monats $m im jahr $y mit der POSIX funktion mktime
# jahr 1900 ist 0, 2013 ist 113 fuer POSIX
# monate ab 0 gezaehlt (0=januar)
# tage ab 1 gezaehlt
my $time_t=POSIX::mktime( 0, 0, 0, 1, $m-1, $y-1900 ) || 0;
# den wochentag bestimmen (0=sonntag)
my $wday=(localtime($time_t))[6];
if ($wday==5) {
printf "# %02d.%04d\n",$m,$y;
}
}
}
Und siehe da: das ist gar nicht mal so selten. Man findet zwar in der Liste auch Jahre, in denen kein solches Vorkommnis vorkommt ;) (Sie sehen, dass Sie nichts sehen ...), aber es gibt auch Jahre mit sogar zwei Monaten, in denen der 1. auf einen Freitag fällt.
$ perl test.pl 2000 2019
# 12.2000
# 03.2002
# 08.2003
# 10.2004
# 07.2005
# 12.2006
# 08.2008
# 05.2009
# 01.2010
# 10.2010
# 07.2011
# 03.2013
 Wenn ich mein Skript von 1900 bis 2099 suchen lasse, finde ich insgesamt 198 Treffer.
$ perl test.pl 1900 2099 |wc -l
198