From Eric Veneto, mathematical madmen are on the loose:

The year is 2000, and an arithmetical anarchist group has an idea. For the next 100 years, it will vandalize a famous landmark whenever the year (in two-digit form, for example this year is “18”) is the product of the month and date (i.e. month × date = year, in the MM/DD/YY format).

https://fivethirtyeight.com/features/when-will-the-arithmetic-anarchists-attack/


In [1]:
import datetime
from collections import Counter

In [2]:
start = datetime.date(2001, 1, 1)
end = datetime.date(2100, 1, 1) - datetime.timedelta(days=1)

In [3]:
d = start
anarchy_dates = []
delta = datetime.timedelta(days=1)
while d <= end:
    if d.day * d.month == d.year % 100:
        anarchy_dates.append(d)
    d += delta
    
anarchy_dates.sort()

How many attacks will happen between the beginning of 2001 and the end of 2099


In [4]:
len(anarchy_dates)


Out[4]:
212

What year will see the most vandalism?


In [5]:
date_counts = Counter(d.year for d in anarchy_dates)

In [6]:
_, max_attacks = date_counts.most_common()[0]
_, min_attacks = date_counts.most_common()[-1]

In [7]:
for year, attacks in date_counts.items():
    if attacks == max_attacks:
        print(f'{attacks} attacks in year {year}')


7 attacks in year 2024

The least?


In [8]:
for year, attacks in date_counts.items():
    if attacks == min_attacks:
        print(f'{attacks} attacks in year {year}')


1 attacks in year 2001
1 attacks in year 2013
1 attacks in year 2017
1 attacks in year 2019
1 attacks in year 2023
1 attacks in year 2029
1 attacks in year 2031
1 attacks in year 2034
1 attacks in year 2038
1 attacks in year 2039
1 attacks in year 2046
1 attacks in year 2049
1 attacks in year 2051
1 attacks in year 2057
1 attacks in year 2065
1 attacks in year 2068
1 attacks in year 2069
1 attacks in year 2076
1 attacks in year 2085
1 attacks in year 2087
1 attacks in year 2091
1 attacks in year 2092
1 attacks in year 2093
1 attacks in year 2095
1 attacks in year 2098

What will be the longest gap between attacks?


In [9]:
gaps = [this-previous for this,previous in zip(anarchy_dates[1:], anarchy_dates)]

In [10]:
max_gap = max(gaps)

for i, gap in enumerate(gaps):
    if gap == max_gap:
        print(f'{gap.days} days between {anarchy_dates[i-1]} and {anarchy_dates[i]}')


1097 days between 2056-08-07 and 2057-03-19