From The Sunday Times, 1st October 1978 [link]

Margaret was demonstrating the use of a pocket calculator to her grandfather. (Keyboard shown above). It was of the type having algebraic logic, which does continuous mixed calculations (e.g. 5 + 2 × 3 = 21). She also demonstrated that keying two consecutive operations results in the second taking preference (e.g. 5 +× 2 = 10).
Margaret asked grandfather to calculate 80 × 5 + 40 − 10; but unfortunately grandfather’s hands were a little shaky and he was prone to strike keys horizontally oг vertically adjacent to the correct one.
Having entered the sum grandfather was about to press the = key (fortunately he hadn’t pressed it before) when Margaret stopped him.
“You have made just two errors so far, and they were consecutive”, she said, “but don’t worry, if you divide by your age on your next birthday, then press the = key, you will get the correct answer to the calculation”.
Grandfather completed the calculation and correctly pressed the = key.
“Wrong again”, said Margaret, “interesting answer though — if you deduct grandmother’s age, and take the cube root of the remainder, you will get the sum of your age, and mine, on our last birthdays”.
How old are Margaret, grandmother and grandfather?
Another early calculator-based puzzle.
This puzzle is included in the book The Sunday Times Book of Brain-Teasers: Book 2 (1981). The puzzle text above is taken from the book.
[teaser895]
Jim Randell 9:29 am on 3 October 2026 Permalink |
Here is a solution using the [
SubstitutedExpression] solver from the enigma.py libraryIt allocates values 1..5 (representing 11..15) to each attribute for each girl.
It runs in 114ms. (Internal runtime of the generated code is 213µs).
And here is a short Python program to run the solver and prettify the output:
from enigma import (SubstitutedExpression, chunk, printf) # construct the solver p = SubstitutedExpression.from_file(["{dir}/teaser2340.run"]) # run the solver for s in p.solve(verbose=0): # output solution names = ["Gina", "Hilda", "Iris", "Jane", "Katy"] attrs = ["age", "house", "class", "desk", "pos"] for (name, ks) in zip(names, chunk("ABCDEFGHIJKLMNPQRSTUVWXYZ", 5)): printf("{name:6s} \\", name=name + ":") for (v, k) in zip(attrs, ks): printf("{v}={x} \\", x=s[k] + 10) printf() printf()Solution: For Katy: age = 11, house = 13, class = 15, desk = 12, position = 14th.
The complete table is:
LikeLike
Frits 10:44 am on 3 October 2026 Permalink |
from itertools import permutations # check for different numbers per column check = lambda g: all(len(s := [x for x in r if x]) == len(set(s)) for r in zip(*g)) # age, house number, classroom number, desk number and position dgts = set(range(11, 16)) # define grid g = [[0] * 5 for _ in range(5)] # "Gina has house 14, classroom 11, desk 13 g[0][1:4] = [14, 11, 13] # "Hilda has position 13, desk 15" g[1][3:] = [15, 13] # "Iris has classroom 14" g[2][2] = 14 sols, orig = set(), [list(r) for r in g] # Gina for g[0][0], g[0][4] in permutations(dgts.difference(orig[0]), 2): # Hilda for g[1][0], g[1][1], g[1][2] in permutations(dgts.difference(orig[1]), 3): if not check(g): continue # Iris for g[2][0], g[2][1], g[2][3], g[2][4] \ in permutations(dgts.difference(orig[2]), 4): if not check(g): continue # Jane for g[3] in permutations(dgts, 5): # Jane is not [age] 13 if g[3][0] == 13 or not check(g): continue # Jane has the same house number as Katy's desk number g[4][3] = g[3][1] # Kate for g[4][0], g[4][1], g[4][2], g[4][4] \ in permutations(dgts - {g[4][3]}, 4): if not check(g): continue sols.add(tuple(g[4])) g[4] = orig[4] g[3] = orig[3] g[2] = orig[2] print("answer:", ' or '.join(str(x) for x in sols))LikeLike
Frits 11:10 am on 3 October 2026 Permalink |
from itertools import permutations # check for different numbers per column check = lambda g: all(len(s := [x for x in r if x]) == len(set(s)) for r in zip(*g)) dgts = set(range(11, 16)) # define constants (G, H, I, J, K), (a, h, c, d, p) = (0, 1, 2, 3, 4), (0, 1, 2, 3, 4) # define grid g = [[0] * 5 for _ in range(5)] # Gina has house 14, classroom 11, desk 13 g[G][1:4] = [14, 11, 13] # Hilda has position 13, desk 15 g[H][3:] = [15, 13] # Iris has classroom 14 g[I][c] = 14 sols, orig = set(), [list(r) for r in g] # Gina (choose age and house number) for g[G][a], g[G][p] in permutations(dgts.difference(orig[G]), 2): # Hilda (choose age, house number and classroom number) for g[H][a], g[H][h], g[H][c] in permutations(dgts.difference(orig[H]), 3): if not check(g): continue # Iris (choose age, house number, desk number and position) for g[I][a], g[I][h], g[I][d], g[I][p] \ in permutations(dgts.difference(orig[I]), 4): if not check(g): continue # Jane for g[J] in permutations(dgts, 5): # Jane has the same house number as Katy's desk number g[K][d] = g[J][h] # Jane is not [age] 13 if g[J][a] == 13 or not check(g): continue # Kate (choose age, house number, classroom number and position) for g[K][a], g[K][h], g[K][c], g[K][p] \ in permutations(dgts - {g[K][d]}, 4): if not check(g): continue sols.add(tuple(g[K])) g[K] = orig[K] g[J] = orig[J] g[I] = orig[I] print("answer:", ' or '.join(str(x) for x in sols))LikeLike
Frits 12:16 pm on 3 October 2026 Permalink |
Using constant variables instead of hardcoded digits slowed things down.
Calculating the numbers for Kate out of the remaining column values also seems to cause a higher run time.
LikeLike