# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1771: Squares either way

From New Scientist #2939, 19th October 2013 [link]

Whether you write dates in the order day.month.year or month.day.year (in each case with two digits for each element), 04.04.01 represents 4 April 2001, and it is a square date because 40401 is the square of 201.

In addition to 4 April 2001, there is one other date in this century that is written in exactly the same way in each order and is also a square date.

1) What is that date?
2) What is the next date after today that is a square date if written in the order day.month.year?
3) What is the next date after today that is a square date if written in the order month.day.year?

Give each answer in the form of 4 April 2001.

[enigma1771]

### 3 responses to “Enigma 1771: Squares either way”

1. Jim Randell 16 October 2013 at 7:22 pm

This Python program uses the standard Python date library to validate dates, and if you have an English locale it should output the dates in the required format. It runs in 38ms.

```from datetime import date
from enigma import irange, printf

# today's date
today = date(2013, 10, 16)

# convert y, m, d to a valid date, or None if invalid
def to_date(y, m, d):
try:
return date(2000 + y, m, d)
except ValueError:
return None

# format a date
def fmt(t):
return t.strftime("%d %B %Y").lstrip('0')

# record dmy and mdy square dates
(d1, d2) = ([], [])

# consider 5- and 6-digit squares
for i in irange(101, 557):
s = "{:06d}".format(i * i)
(x, y, z) = (int(t) for t in (s[0:2], s[2:4], s[4:6]))
dmy = to_date(z, y, x)
mdy = to_date(z, x, y)
if dmy: d1.append(dmy)
if mdy: d2.append(mdy)

# (1) dates that represent the same way
for t in d1:
if t.day == t.month and t in d2:
printf("(1) {t}", t=fmt(t))

# (2) first dmy date after today
for t in sorted(d1):
if t > today:
printf("(2) {t}", t=fmt(t))
break

# (3) first mdy date after today
for t in sorted(d2):
if t > today:
printf("(3) {t}", t=fmt(t))
break
```

Solution: (1) 7 July 2056. (2) 6 May 2016. (3) 8 January 2016.

2. Brian Gladman 16 October 2013 at 8:44 pm

I didn’t like this one much.

```from itertools import product
from datetime import date

# question one
for y, dm in product(range(100), range(1, 13)):
x = 10100 * dm + y
if round(x ** 0.5) ** 2 == x:
print('1)', date(2000 + y, dm, dm).strftime('%d %B %Y').lstrip('0'))

# question two
for y, m, d in product(range(13, 100), range(1, 32), range(1, 13)):
x = 100 * (100 * d + m) + y
if round(x ** 0.5) ** 2 == x:
print('2)', date(2000 + y, m, d).strftime('%d %B %Y').lstrip('0'))
break

# question three
for y, m, d in product(range(13, 100), range(1, 32), range(1, 13)):
x = 100 * (100 * m + d) + y
if round(x ** 0.5) ** 2 == x:
print('3)', date(2000 + y, m, d).strftime('%d %B %Y').lstrip('0'))
break
```
• Brian Gladman 17 October 2013 at 8:08 am

A correction of a stupid error and a small speed up.

```from itertools import product
from datetime import date

# quadratic residues mod 100 for years
q = sorted(set((x * x) % 100 for x in range(100)))

# question one
for y, dm in product(q, range(1, 13)):
x = 10100 * dm + y
if round(x ** 0.5) ** 2 == x:
print('1)', date(2000 + y, dm, dm).strftime('%d %B %Y').lstrip('0'))

# question two
for y, m, d in product(q, range(1, 13), range(1, 32)):
if y > 12:
x = 100 * (100 * d + m) + y
if round(x ** 0.5) ** 2 == x:
print('2)', date(2000 + y, m, d).strftime('%d %B %Y').lstrip('0'))
break

# question three
for y, m, d in product(q, range(1, 13), range(1, 32)):
if y > 12:
x = 100 * (100 * m + d) + y
if round(x ** 0.5) ** 2 == x:
print('3)', date(2000 + y, m, d).strftime('%d %B %Y').lstrip('0'))
break
```

This site uses Akismet to reduce spam. Learn how your comment data is processed.