# Enigmatic Code

Programming Enigma Puzzles

## Enigma 426: Time and again

From New Scientist #1576, 3rd September 1987 [link]

Time and again, you’ve been asked to sort out letters-for-digits puzzles, where digits are consistently replaced by letters, different letters being used for different digits. Today, that recurring theme is used in a truly recurring way. The fraction on the left (which is in its simplest form) represents the recurring decimal on the right. Should you want an extra optional clue, I can also tell you that the last two digits of the numerator of the fraction are equal.

What is AGAIN?

[enigma426]

### 3 responses to “Enigma 426: Time and again”

1. Jim Randell 11 December 2017 at 8:09 am

A little bit of analysis:

If the numerator of the fraction is x, we can derive the integer equation:

(10^8 – 1)x = TIME × ANDAGAIN

Using the extra optional clue, we can consider numerators of the form abb, which means we only have to consider two digit numbers of the form ab and then we can just add an extra b digit to the end. So we only have to check 90 values for x.

This Python program runs in 97ms.

Run: [ @repl.it ]

```from enigma import irange, divisors_pairs, gcd, nsplit, printf

# numerator x in the form abb (it is possible that a = b)
for ab in irange(10, 99):
x = (ab * 10) + (ab % 10)
for (TIME, ANDAGAIN) in divisors_pairs(99999999 * x):
# TIME has 4 digits
if TIME < 1000: continue
if TIME > 9999: break

# and x / TIME is a fraction in its simplest form
if gcd(x, TIME) != 1: continue

# TIME consists of 4 distinct digits
(T, I, M, E) = nsplit(TIME)
if not(len(set((T, I, M, E))) == 4): continue

# check the digits in ANDAGAIN
ds = nsplit(ANDAGAIN)
if len(ds) != 8: continue
(A, N, D, A1, G, A2, I1, N1) = ds
if not(A == A1 == A2 and N == N1 and I == I1 and len(set((T, I, M, E, A, N, D, G))) == 8): continue

printf("AGAIN = {AGAIN} [{x} / {TIME} = 0.({ANDAGAIN})...]", AGAIN=ANDAGAIN % 100000)
```

Solution: AGAIN = 38354.

The actual expression is:

522 / 1507 = 0.(34638354)…

where the digits in brackets repeat indefinitely.

Without the extra clue we can consider all three digit values of x from 100 to 999 (900 values), which takes the above program 289ms to consider.

But without being told anything about the “shape” of x we can solve the puzzle as an alphametic, and find that there is only one solution. (Even when the fraction is allowed to be not in lowest terms).

This Python program uses the [[ `SubstitutedExpression()` ]] solver from the enigma.py library and runs in 557ms.

```from enigma import SubstitutedExpression, gcd, printf

# express the puzzle as an alphametic expression
p = SubstitutedExpression(
[ "(TIME * ANDAGAIN) % 99999999 = 0" ],
d2i={ 0: 'T' },
)

# solve the alphametic
for (s, (TIME, ANDAGAIN)) in p.solve():
# extract the numerator of the fraction
x = (TIME * ANDAGAIN) // 99999999
# check the fraction is in lowest terms
if gcd(x, TIME) != 1: continue
# output the solution
printf("{x} / {TIME} = 0.({ANDAGAIN})...")
```
2. Brian Gladman 11 December 2017 at 10:15 pm
```from number_theory import divisor_pairs

# Using the extra clue the expression is equivalent
# to: XYY * (10^8 - 1) = TIME * ANDAGAIN

# try possible numerators of form XYY
for xy in range(10, 100):
xxy = 10 * xy + xy % 10
# split the right hand side into two factors
for time, andagain in divisor_pairs(xxy * (10 ** 8 - 1)):
# extract eight different digits and check duplicates
try:
T, I, M, E = str(time)
A, N, D, a1, G, a2, i, n = str(andagain)
if not (a1 == a2 == A and i == I and n == N
and len({A, D, E, G, I, M, N, T}) == 8):
raise ValueError
except ValueError:
continue
print(' ' * 26 + '_' * 8)
print(f'AGAIN = {andagain % 100000} ({xxy}/{time}=0.{andagain})')
```
3. geoffrounce 12 December 2017 at 5:03 pm
```digits = set('1234567890')

from itertools import permutations
for p1 in permutations(digits, 5):
a, g, i, n, d = p1
if a == '0': continue
again = int(a + g + a + i + n)
andagain = int(a + n + d + a + g + a + i + n)

p2 = digits.difference(p1)
for q1 in permutations(p2, 3):
t, m, e  = q1
if t == '0': continue
time = int(t + i + m + e)
xyy, r = divmod(time * andagain, 10 ** 8 - 1)
if not r:
print("AGAIN = ", again)

#AGAIN =  38354
```

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