From The Sunday Times, 20th December 1998 [link]
I have received an astonishing letter from a fellow puzzle-setter. He writes:
“I am sending you a puzzle in the form of a parcel consisting of an opaque box containing some identical marbles, each weighing a whole number of grams, greater than one gram. The box itself is virtually weightless. If I told you the total weight of the marbles, you could work out how many there are.”
He goes on:
“To enable you to work out the total weight of the marbles I am also sending you a balance and a set of equal weights, each weighing a whole number of grams, whose total weight is two kilograms. Bearing in mind what I told you above, these weights will enable you to calculate the total weight of the marbles and hence how many marbles there are.”
I thought that he was sending me these items under seperate cover, but I had forgotten how mean he is. He went on:
“I realise that I can save on the postage. If I told you the weight of each weight you would still be able to work out the number of marbles. Therefore I shall not be sending you anything.”
How many marbles were there?
This puzzle is included in the book Brainteasers (2002). The puzzle text above is taken from the book.
[teaser1892]
Jim Randell 12:18 pm on 29 October 2020 Permalink |
When rhyme was written the daughter’s age was some prime d, the father’s age some prime f, and (d + f) is a square number.
Unless they were born on the same day at the same time one of them have their next birthday before the other.
If it is the daughter, the ages progress like this:
And if the father has the next birthday, the ages progress like this:
So we just need to examine these sequences to look for two more occurrences of the ages being prime, and their sum being a square.
This Python program runs in 44ms.
from enigma import (primes, is_square, printf) # primes for ages primes.expand(150) # check for viable ages check = lambda a, b: a in primes and b in primes and is_square(a + b) # extend the list to length k, with birthdays a then b def extend(a, b, k=3): rs = [(a, b)] while a < 150 and b < 150: a += 1 if check(a, b): rs.append((a, b)) b += 1 if check(a, b): rs.append((a, b)) if not (len(rs) < k): return rs # consider the daughter's at the time of the rhyme for d in primes.between(2, 16): # now consider possible ages for the father for f in primes.between(d + 16, 50): # together they make a square if not is_square(d + f): continue # solutions where daughters birthday is next rs = extend(d, f) if rs: printf("d -> f: {rs}") # solutions where fathers birthday is next rs = extend(f, d) if rs: printf("f -> d: {rs}")Solution: Today the daughter is 7 and the father is 29.
The three pairs of ages are:
So father’s birthday came first after the rhyme was written.
LikeLike
Frits 1:44 pm on 29 October 2020 Permalink |
from enigma import SubstitutedExpression, is_prime, is_square # the alphametic puzzle p = SubstitutedExpression( [# father (age CDE) is a lot older than daughter (age AB) "AB + 15 < CDE", "PQ > 0", "RS > 0", # daughter must have already been born PQ years ago (and prime) # "when she was a little girl" "0 < AB - PQ < 10", # maximum age father "CDE < 125", "CDE + RS < 125", # PQ years ago "is_prime(AB - PQ - w)", "is_prime(CDE - PQ - x)", "is_square(AB + CDE - 2 * PQ - w - x)", # now "is_prime(AB)", "is_prime(CDE)", "is_square(AB + CDE)", # RS years later "is_prime(AB + RS + y)", "is_prime(CDE + RS + z)", "is_square(AB + CDE + 2 * RS + y + z)", # uncertainty bits, not both of them may be true "x + w < 2", "y + z < 2", ], answer="AB, CDE, PQ, RS, w, x, y, z", symbols="ABCDEPQRSwxyz", verbose=0, d2i=dict([(k, "wxyz") for k in {2,3,4,5,6,7,8,9}]), distinct="", # allow variables with same values #reorder=0, ) # Print answer for (_, ans) in p.solve(): print(f"ages daughter {ans[0] - ans[2] - ans[4]} {ans[0]} " f"{ans[0] + ans[3] + ans[6]}") print(f"ages father {ans[1] - ans[2] - ans[5]} " f"{ans[1]} {ans[1] + ans[3] + ans[7]}") print(f"squares {ans[0] + ans[1] - 2*ans[2] - ans[4] - ans[5]} " f"{ans[0] + ans[1]} {ans[0] + ans[1] + 2*ans[3] + ans[6] + ans[7]}") # ages daughter 2 7 61 # ages father 23 29 83 # squares 25 36 144LikeLike
Frits 4:16 pm on 29 October 2020 Permalink |
from enigma import printf # Prime numbers up to 124 P = [2, 3, 5, 7] P += [x for x in range(11, 100, 2) if all(x % p for p in P)] P += [x for x in range(101, 125, 2) if all(x % p for p in P)] # report two prime numbers (ascending) which sum to <n> def twoprimes(n, dif=0): li = [] i = 1 p1 = 2 while(p1 < n - p1): if n - p1 in P: # difference between primes is not exact if dif == 0 or (dif - 1 <= abs(n - 2 * p1) <= dif + 1): li.append([p1, n - p1]) p1 = P[i] i += 1 return li # square candidates for when daughter was a little girl for i in range(4, 11): # also allowing for people like B. Ecclestone for t1 in twoprimes(i * i): # "when she was a little girl" if t1[0] > 9: continue dif1 = int(t1[1]) - int(t1[0]) # square candidates for now for j in range(i + 1, 15): for t2 in twoprimes(j * j, dif1): # square candidates for in te future for k in range(j + 1, 16): for t3 in twoprimes(k * k, dif1): printf("{t1[0]} + {t1[1]} = {su}", su = int(t1[0]) + int(t1[1])) printf("{t2[0]} + {t2[1]} = {su}", su = int(t2[0]) + int(t2[1])) printf("{t3[0]} + {t3[1]} = {su}", su = int(t3[0]) + int(t3[1]))LikeLike
GeoffR 9:23 pm on 29 October 2020 Permalink |
% A Solution in MiniZinc include "globals.mzn"; % Three Daughters' ages % D1 = young girl, D2 = age now, D3 = future age var 1..10:D1; var 1..50:D2; var 1..80:D3; % Three corresponding Fathers ages var 13..40:F1; var 13..70:F2; var 13..105:F3; % All Fathers and Daughters ages are different constraint all_different ([F1, F2, F3, D1, D2, D3]); set of int: primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103}; set of int : squares = {16, 25, 36, 49, 64, 81, 100, 121, 144, 169}; % Age group constraints constraint F1 - D1 > 12 /\ D1 < 10 ; constraint D2 > D1 /\ D3 > D2; constraint F2 > F1 /\ F3 > F2; constraint F1 > D1 /\ F2 > D2 /\ F3 > D3; % 1st age differences between Father and Daughter constraint D2 - D1 = F2 - F1 + 1 \/ D2 - D1 = F2 - F1 - 1; % Age difference is the same between the 2nd and 3rd age groups constraint F2 - D2 == F3 - D3; constraint F3 - F2 == D3 - D2; % All ages are prime numbers constraint F1 in primes /\ F2 in primes /\ F3 in primes; constraint D1 in primes /\ D2 in primes /\ D3 in primes; % All father and daughter group sums are squares constraint (F1 + D1) in squares /\ (F2 + D2) in squares /\ (F3 + D3) in squares; solve satisfy; output[ "Father's ages in sequence are " ++ show(F1) ++ ", " ++ show(F2) ++ ", " ++ show(F3) ++"\nDaughters ages in sequence are " ++ show(D1) ++ ", " ++ show(D2) ++ ", " ++ show(D3) ]; % Father's ages in sequence are 23, 29, 83 % Daughters ages in sequence are 2, 7, 61 % ---------- % ==========LikeLike
Frits 10:25 am on 30 October 2020 Permalink |
I feel lines 11 and 12 are too restrictive. However, removing them gives the same result.
LikeLike
GeoffR 5:16 pm on 30 October 2020 Permalink |
@Frits:
The constraint programming approach is to search for a state of the world in which a large number of constraints are satisfied at the same time. But we cannnot predict in advance which constraints are required for a solution. It is, of course, a different approach to imperative programming e.g. Python.
It is therefore possible to cancel one or two constraints and still get a solution.
We soon know if we have not got sufficient constraints when we don’t get a solution.
Lines 11 and 12 are logical in that we know over several time scales that all the fathers and daughters ages will be different, so it is quite OK to make this a constraint, in my view.
As an experiment, I remmed out Lines 22, 23 and 24, leaving Line 12 functional. This still gave the correct solution. I then remmed out Line 12 and I got three solutions – one correct and two wrong.
This shows that Line 12 constraint is related to the constraints on Lines 22,23 and 24 in functionality.
So we could equally say that Lines 22,23 and 24 could be removed, providing Line 12 was not removed.
I think all the constraints I used have a reasonable basis, so it is probably best not to tinker with individual constraints and let constraint programming use its own internal procedures to find a solution.
LikeLike
Frits 11:26 am on 31 October 2020 Permalink |
@GeoffR,
My only point is that this particular constraint is not part of the requirements and can potentially give cause to miss certain solutions.
You say that “we know over several time scales that all the fathers and daughters ages will be different”. I think it is possible the daughter “today” can have the same age as her father at the time she was a little girl (same for later on).
Example (if we forget about primes):
Father’s ages in sequence are 23, 44, 83
Daughters ages in sequence are 2, 23, 62
You may be right if the line 11/12 constraint emerges from all the requirements but that is not immediately clear to me.
LikeLike