Brain-Teaser 24: [Shades of Gray]
From The Sunday Times, 3rd September 1961 [link]
Someone here in Land’s End Lane of the name of Roger Gray (or is it “Grey”? I never can remember which), seems gratified to find that by allotting distinctive digits against appropriate letters of the alphabet he can, by substituted figures for letters, make an addition sum of his name, the answer to which, converted back into letters in similar manner, spells his house number.
There seems nothing particularly surprising in this, for if it really is “Gray” and if he happened to live at No. 7, as I do, all he would have to do would be to write:
and substitute say:
However, he doesn’t live at No. 7, and moreover, I happen to know that there’s an 8 in his sum.
So where does Roger live, and what is his sum?
This puzzle was originally published with no title.
[teaser24]


Jim Randell 8:26 am on 28 February 2021 Permalink |
The house number must be 5 or 6 letters, so there is only a limited number of possibilities.
We can use some handy routines from the enigma.py library to solve this puzzle. The [[
int2words()]] function converts a number into English, and then we can use the [[SubstitutedSum()]] solver to find solutions to the corresponding alphametic sums.The following Python program runs in 127ms.
from enigma import (irange, int2words, translate, SubstitutedSum, printf) # suppose the house number is n (not 7) for n in irange(1, 100): if n == 7: continue word = translate(int2words(n).upper(), (lambda x: x if x.isalpha() else '')) if not (4 < len(word) < 7): continue # construct the alphametic sum for terms in [('ROGER', 'GRAY'), ('ROGER', 'GREY')]: p = SubstitutedSum(terms, word) for s in p.solve(verbose=0): # one of the letters has to be 8 if not (8 in s.values()): continue # output solution printf("{p.text} / {t}", t=p.substitute(s, p.text))Solution: Roger Gray lives at number 12. The sum is: 94729 + 7953 = 102682.
LikeLike
Frits 10:43 pm on 1 March 2021 Permalink |
Only calling SubstitutedExpression once, looking for trouble.
In order to get a decent run time (1 second with PyPy) I had to use some analysis (like skipping all the words ending on “Y”). Only 4 words (THREE, EIGHT, ELEVEN and TWELVE) remain to be checked.
from enigma import SubstitutedExpression, int2words, translate def check(num, txt): # txt has format (_.....) # first letter may not be zero if len(str(num)) < len(txt) - 3: return False # number of different digit must match number of letters return len(set(str(num))) == len(set(txt)) - 3 words = [] # suppose the house number is n for n in range(1, 100): if n == 7: continue word = translate(int2words(n).upper(), (lambda x: x if x.isalpha() else '')) if not(4 < len(word) < 7): continue # units: R + Y can't be equal to Y (else R would have to be zero) if word[-1] == "Y": continue words.append(word) lower = "".join([x for x in "abcdefghijklmnopqrstuvwxyz" if x not in "if else or and not sum check str"]) bits = lower[:len(words)] exprs = ["sum([" + ','.join(bits) + "]) == 1"] for i, word in enumerate(words): if len(word) == 6: exprs.append(bits[i] + " == 0 or R == 9") exprs.append(bits[i] + " == 0 or " + word[0] + " == 1") exprs.append(bits[i] + " == 0 or Y - 1 == " + word[-1]) else: exprs.append(bits[i] + " == 0 or " + word[0] + " - 1 == R") exprs.append(bits[i] + " == 0 or " + word + " - ROGER in {GRAY, GREY}") exprs.append(bits[i] + " == 0 or '8' in str(" + word + ")") exprs.append(bits[i] + " == 0 or check(" + word + ", '" + word + "')") # collect letters not used in words, they can't have value 8 outside = "".join([x for x in "ROGEYA" if x not in "".join(words)]) symbols = "".join(set("ROGEYA" + "".join(words))) + bits dist = ["ROGEYA" + c for c in [x for x in set(''.join(words)) if x not in "ROGEYA"]] # puzzle p = SubstitutedExpression( exprs, symbols=symbols, distinct=dist, answer="(ROGER + GRAY if '8' in str(ROGER + GRAY) else ROGER + GREY), " + " + ".join([x + ' * ' + str(i) for i, x in enumerate(bits)]), env=dict(check=check), verbose=0, d2i=dict([(0, "RG")] + [(k, bits) for k in range(2, 8)] + [(8, outside + bits)] + [(9, bits)]) ) # print answer sol = set() for (_, ans) in p.solve(): sol.add(words[ans[1]] + " = " + str(ans[0])) print(*sol)LikeLike