# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1173: Six months

From New Scientist #2329, 9th February 2002 [link]

The months MAY, JUN, JUL and AUG are indicated in the two multiplications shown where all the digits have been replaced by capital letters and asterisks. In these multiplications, and in the clues that follow, different capital letters stand for different digits but the same capital letter always stands for the same digit while the asterisks can be any digit.

Typically, the months JAN and MAR are both exactly divisible by 31, and of course you can also assume that any YEAR is exactly divisible by 12 or even 52.

What is the product of each multiplication?

[enigma1173]

### 3 responses to “Enigma 1173: Six months”

1. Jim Randell 4 April 2016 at 7:44 am

This Python program runs in 37ms.

from collections import defaultdict
from itertools import permutations, product
from enigma import irange, split, nconcat, divc, divf, printf

# possible digits
digits = set(irange(0, 9))

# generate solutions for a multiplication sum: abc * xyz
# where the result is 5-digits and each of the intermediate products is 3-digits
# the final intermediate product, abc * x is given (as p)
def multiplication(p):
# p = abc * x
for x in irange(1, 9):
(abc, r) = divmod(p, x)
if abc < 100: break
if r > 0: continue

# (abc * y) and (abc * z) are also 3-digit numbers
for (y, z) in product(irange(divc(100, abc), divf(999, abc)), repeat=2):
xyz = nconcat(x, y, z)
# the result of the sum is ...
r = abc * xyz
if r > 99999: continue
yield (abc, xyz, r)

# find 3-digit multiples of 31 with distinct digits
# and record them by the middle digit
r = defaultdict(list)
for i in irange(4, 32):
n = i * 31
(x, y, z) = split(n, int)
if len(set((x, y, z))) == 3:
r[y].append(n)

# consider values of A
for (A, vs) in r.items():
# and corresponding values for JAN and MAR
for (JAN, MAR) in permutations(vs, 2):
(J, _, N) = split(JAN, int)
(M, _, R) = split(MAR, int)
# remaining digits
ds1 = digits.difference([J, A, N, M, R])
if len(ds1) != 5: continue

# consider possible values for Y and E
for (Y, E) in permutations(ds1, 2):
if Y == 0: continue
# YEAR is a multiple of lcm(12, 52) = 156
YEAR = nconcat(Y, E, A, R)
if YEAR % 156 > 0: continue

# remaining digits
ds2 = ds1.difference([E, Y])

# solve the first multiplication sum
MAY = nconcat(M, A, Y)
for (a1, b1, r1) in multiplication(MAY):
(J1, U, N1, _, _) = split(r1, int)
if not(J1 == J and N1 == N and U in ds2): continue

# the remaining letters are G and L (in some order)
for (G, L) in permutations(ds2.difference([U])):

# solve the second multiplication sum
JUL = nconcat(J, U, L)
for (a2, b2, r2) in multiplication(JUL):
(A1, U1, G1, _, _) = split(r2, int)
if not(A1 == A and U1 == U and G1 == G): continue

printf("{a1} x {b1} = {r1}, {a2} x {b2} = {r2} [JAN={JAN} MAR={MAR} YEAR={YEAR}, U={U} G={G} L={L}]")

Solution: The result of the first multiplication sum is 35109. The result of the second multiplication sum is 45696.

The complete multiplication sums are shown below:

JAN = 341 (11×31), MAR = 248 (8×31), YEAR = 9048 (754×12, 174×52).

• Jim Randell 12 August 2016 at 1:29 pm

It is possible to use the generalised alphametic solver (SubstitutedExpression()) from the enigma.py library to solve this one. And it can be called directly from the command line without having to write a program.

We could introduce 28 additional symbols for the asterisks (using the --symbols="<string>" parameter) and then use the --distinct="<string>" parameter to limit the letters actually given in the diagram to be distinct, while the the remaining additional symbols can take on any value. This would allow us to read off the values for the complete sums from the solution.

But as we don’t care about most of their values here I have just used additional symbols (lower case letters) for the multiplicands of the sums, and then I have used expressions to ensure that the intermediate multiplications in the sums are the correct “shape”.

Finally the --answer="<expr>" parameter is used to display the results of the sums.

% python -m enigma SubstitutedExpression \
--symbols="AEGJLMNRUYabcdefghijkl" --distinct="AEGJLMNRUY" \
--answer="(abc * def, ghi * jkl)" \
"(abc * def) // 100 = JUN" \
"99 < abc * f < 1000" \
"99 < abc * e < 1000" \
"abc * d = MAY" \
"(ghi * jkl) // 100 = AUG" \
"99 < ghi * l < 1000" \
"99 < ghi * k < 1000" \
"ghi * j = JUL" \
"JAN % 31 = 0" "MAR % 31 = 0" \
"YEAR % 12 = 0" "YEAR % 52 = 0"
((abc * def) // 100 = JUN) (99 < abc * f < 1000) (99 < abc * e < 1000) (abc * d = MAY) ((ghi * jkl) // 100 = AUG) (99 < ghi * l < 1000) (99 < ghi * k < 1000) (ghi * j = JUL) (JAN % 31 = 0) (MAR % 31 = 0) (YEAR % 12 = 0) (YEAR % 52 = 0)
((249 * 141) // 100 = 351) (99 < 249 * 1 < 1000) (99 < 249 * 4 < 1000) (249 * 1 = 249) ((119 * 384) // 100 = 456) (99 < 119 * 4 < 1000) (99 < 119 * 8 < 1000) (119 * 3 = 357) (341 % 31 = 0) (248 % 31 = 0) (9048 % 12 = 0) (9048 % 52 = 0) / A=4 E=0 G=6 J=3 L=7 M=2 N=1 R=8 U=5 Y=9 a=2 b=4 c=9 d=1 e=4 f=1 g=1 h=1 i=9 j=3 k=8 l=4 / (35109, 45696)
(abc * def, ghi * jkl) = (35109, 45696) [1 solution]

The command runs in 178ms.

2. Brian Gladman 5 April 2016 at 10:25 pm
from itertools import permutations, product

# generate 3 x 3 digit multiplications in which all partial
# products (less trailing zeros) have 3 digits, one is 'pp'
# and the result has 5 digits with the top 3 matching 'pr'
def mult(pp, pr):
# test the divisors of the partial product
for b3 in range(1, 10):
if not pp % b3:
# for those that give a possible 3 digit multiplier
top = pp // b3
if top < 100:
break
# now check for the lower 2 digits of the other mutiplier
r = range(99 // top + 1, 999 // top + 1)
for b2, b1 in product(r, repeat=2):
bot = (100 * b3 + 10 * b2 + b1)
result = top * bot
if result // 100 == pr:
yield result, top, bot

# the year is a 4 digit multiple of 156
for YEAR in range(7 * 156, 10000, 156):
Y, E, A, R = (int(x) for x in str(YEAR))
s1 = set(range(10)).difference([Y, E, A, R])

# find M such that MAR is a multiple of 31
for M in s1:
MAR = 100 * M + 10 * A + R
if not MAR % 31:
s2 = s1.difference([M])

# find J and N such that JAN is a multiple of 31
for J in s2:
N = -(100 * J + 10 * A) % 31
if N != J and N in s2:
s3 = s2.difference([J, N])

# now find U values that give valid multiplications
# for MAY and JUN
for U in s3:
MAY = 10 * (MAR // 10) + Y
JUN = 100 * J + 10 * U + N
for r1, t1, b1 in mult(MAY, JUN):

# permute the two remaining digits for G and L
for G, L in permutations(s3.difference([U]), 2):
JUL = 10 * (JUN // 10) + L
AUG = 100 * A + 10 * U + G

# and test for a JUL/AUG multiplication that is valid
for r2, t2, b2 in mult(JUL, AUG):
fs = 'The results are {} ({} x {}) and {} ({} x {}).'
print(fs.format(r1, t1, b1, r2, t2, b2))