# Enigmatic Code

Programming Enigma Puzzles

## Enigma 304: Enigmatic dates

From New Scientist #1452, 18th April 1985 [link]

In this puzzle dates are written in the form 17/3/08 or 9/12/72 but then the /s are deleted and the digits consistently replaced by letters, different letters represent different digits.

I was born on ENIGMA. So how old was I on EMPTY? I was __ years old (and AGE days to be precise). By the end of 1999 I shall be ON in years.

What’s the POINT?

[enigma304]

### 3 responses to “Enigma 304: Enigmatic dates”

1. Jim Randell 21 August 2015 at 8:44 am

Initially I thought there were two solutions to this problem, but then I remembered that it was originally set in 1985.

This Python code runs in 35ms.

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

digits = set('0123456789')

# ENIGMA is a six-figure date,
# EN is a 2-figure day
for EN in irange(10, 31):
(E, N) = str(EN)
if E == N: continue

# IG is a 2-figure month
for IG in (10, 12):
(I, G) = str(IG)
ds1 = digits.difference((E, N, I, G))
if len(ds1) != 6: continue

# MA is a 2-figure year
for (M, A) in permutations(ds1, 2):
ds2 = ds1.difference((M, A))

# ON is the age at the end of 1999
s = str(99 - int(M + A))
if not(len(s) == 2 and s[1] == N): continue
O = s[0]
ds3 = ds2.difference((O,))
if len(ds3) != 3: continue

# P, T, Y are the remaining letters
for (P, T, Y) in permutations(ds3):
y = 1900 + int(T + Y)
if y > 1985: continue
for (d, m) in ((E + M, P), (E, M + P)):
try:
EMPTY = date(y, int(m), int(d))
except ValueError:
continue

bday = date(y, IG, EN)
if bday > EMPTY: bday = date(y - 1, IG, EN)

if (EMPTY - bday).days == int(A + G + E):
printf("POINT={P}{O}{I}{N}{T} [ENIGMA={E}{N}/{I}{G}/{M}{A} ON={O}{N} EMPTY={EMPTY} AGE={A}{G}{E}]")
```

Solution: POINT = 85167.

Your birth date represented by ENIGMA is 26/10/1943, and the date represented by EMPTY is 24/8/1979, on which date your age is 35 years, 302 days, and 302 corresponding to AGE. At the end of 1999 you will be 56 years old, represented by ON.

If the puzzle had been set after 24/8/1997 then that date could be represented by EMPTY, and your age then would have been 53 years, 302 days. In this case POINT would be 85169.

Line 33 of the program ignores solutions where EMPTY is after 1985.

2. Brian Gladman 22 August 2015 at 5:24 pm
```from itertools import permutations, product
from datetime import date, timedelta

digits = set('0123456789')
# publication year
now = 1985

# compose the first date (ENIGMA), noting that the
# day, month and year all have two digits
for dy, mn in product(range(10, 32), range(10, 13)):
enig = str(dy) + str(mn)
if len(set(enig)) != 4:
continue
for yr in range(10, now % 100):
enigma = enig + str(yr)
r1 = digits.difference(enigma)
# there must now be four digits left
if len(r1) != 4:
continue
E, N, I, G, M, A = enigma
age = int(A + G + E)

# find the year (which must be TY from EMPTY)
for T, Y in permutations(digits.difference(enigma), 2):
y = int(T + Y)
# add AGE days to this date to form EMPTY
d2 = date(1900 + y, mn, dy) + timedelta(days = age)
# the day and the month for EMPTY must have 3 digits
# for which  E and M must match those in ENIGMA
_E, _M, *p = str(d2.day) + str(d2.month)
if not (_E == E and _M == M and len(p) == 1):
continue
P = p[0]

# now find the unused digit for O
O, *r = r1.difference([P, T, Y])
# check that O and N give the correct age at the end of 1999
if not r and yr + int(O + N) == 99:
d1 = date(1900 + yr, mn, dy)
fs = 'POINT = {} (ENIGMA {:%d/%m/%Y}, EMPTY {:%d/%m/%Y}, AGE {})'
print(fs.format(''.join((P, O, I, N, T)), d1, d2, age))
```
3. Brian Gladman 22 August 2015 at 10:16 pm

Jim has kindly pointed out that the above version is flawed. In fact I mistakenly published the wrong version of my code – here is the correct version:

```from itertools import permutations, product
from datetime import date, timedelta

digits = set('0123456789')
# publication year
now = 1985

# compose the first date (ENIGMA), noting that the
# day, month and year all have two digits
for dy, mn in product(range(10, 32), range(10, 13)):
enig = str(dy) + str(mn)
if len(set(enig)) != 4:
continue
for yr in range(10, now % 100):
enigma = enig + str(yr)
r1 = digits.difference(enigma)
# there must now be four digits left
if len(r1) != 4:
continue
E, N, I, G, M, A = enigma
age = int(A + G + E)

# find the year (which must be TY from EMPTY)
for y in range(yr, now % 100):
# add AGE days to this date to form EMPTY
d2 = date(1900 + y, mn, dy) + timedelta(days = age)
# the day and the month for EMPTY must have 3 digits
# for which  E and M must match those in ENIGMA
_E, _M, *p = str(d2.day) + str(d2.month) +str(d2.year % 100)
if not (_E == E and _M == M and len(p) == 3):
continue
P, T, Y = p

# now find the unused digit for O
O, *r = r1.difference([P, T, Y])
# check that O and N give the correct age at the end of 1999
if not r and yr + int(O + N) == 99:
d1 = date(1900 + yr, mn, dy)
fs = 'POINT = {} (ENIGMA {:%d/%m/%Y}, EMPTY {:%d/%m/%Y}, AGE {})'
print(fs.format(''.join((P, O, I, N, T)), d1, d2, age))
```

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