Design a site like this with WordPress.com

## Teaser 3145: Easier to ask the audience

“I have forgotten the phone number!”, complained Martha, about to phone a friend. “So have I!”, replied George, “but I have some vague memories of it. It is a perfect square with all the digits different, and the last digit is equal to the number of digits to be dialled. The last-but-one digit is odd and one of the digits is zero. Also the second and third and last-but-one digits are all exact multiples of the first digit. Maybe you can work it out”.

Martha proceeded to dial the number correctly.

What number did she dial?

Happy New Year from S2T2!

[teaser3145]

• #### Jim Randell 4:47 pm on 30 December 2022 Permalink | Reply

The final digit of the square number tells us how long it is, so we only need to check up to 9 digits, and it must have a “second”, “third”, and “last-but-one” digit, so (assuming these are all different) there need to be at least 5 digits. And to also fit a 0 digit in there must be at least 6 digits.

And a perfect square cannot end with 7 or 8, so we only need to consider 6 or 9 digit numbers.

This Python program just tries all candidate squares in this range (and we could add further analysis to reduce the number of candidates).

It runs in 122ms. (Internal run time is 23.3ms).

Run: [ @replit ]

```from enigma import (powers, inf, nsplit, printf)

# is <x> a (proper) multiple of <n>?
is_multiple = lambda n, x: (x > n > 0 and x % n == 0)

# consider squares with 6 - 9 digits
for n in powers(317, inf, 2):
# split into digits
ds = nsplit(n)
k = len(ds)
# there are at most 9 digits...
if k > 9: break
# but not 7 or 8
if not (k == 6 or k == 9): continue
# ... and they are all different
if not (len(set(ds)) == k): continue
# the final digit is equal to the total number of digits
if not (ds[-1] == k): continue
# the last but one digit is odd
if not (ds[-2] % 2 == 1): continue
# and the digit 0 is used
if not (0 in ds): continue
# the 2nd, 3rd and last but 1 digit are multiples of the 1st digit
if not all(is_multiple(ds[0], ds[i]) for i in (1, 2, -2)): continue
# output solution
printf("n = {n}")
```

Solution: The number is: 173056.

173056 = 416².

Like

• #### Jim Randell 10:37 pm on 31 December 2022 Permalink | Reply

With a bit of analysis we see that a 6-digit square must be of the form 1xx0x6, and so is the square of a number in the range [351, 445] that ends in the digit 4 or 6.

And a 9-digit square must be of the form 1xxxxxxx9, and so is the square of a number in the range [11093, 13698] that ends in the digit 3 or 7. (Thanks to Frits for correcting my upper bound).

This Python program just checks these numbers.

It runs in 52ms. (Internal runtime is 1.2ms).

Run: [ @replit ]

```from enigma import (irange, nsplit, printf)

# is <x> a (proper) multiple of <n>?
is_multiple = lambda n, x: (x > n > 0 and x % n == 0)

def check_n(n):
# split into digits
ds = nsplit(n)
k = len(ds)
# all digits are all different
if not (len(set(ds)) == k): return
# the final digit is equal to the total number of digits
if not (ds[-1] == k): return
# the last but one digit is odd
if not (ds[-2] % 2 == 1): return
# and the digit 0 is used
if not (0 in ds): return
# the 2nd, 3rd and last but 1 digit are multiples of the 1st digit
if not all(is_multiple(ds[0], ds[i]) for i in (1, 2, -2)): return
# output solution
printf("n = {n}")

def check(seq):
for i in seq:
check_n(i * i)

# check 6-digit numbers of the form 1xx0x6
check(irange(354, 444, step=10))
check(irange(356, 436, step=10))

# check 9-digit numbers of the form 1xxxxxxx9
check(irange(11093, 13693, step=10))
check(irange(11097, 13697, step=10))
```

Like

• #### Frits 11:07 am on 1 January 2023 Permalink | Reply

@Jim, I came to the same conclusion but with ranges [351-445] (you probably had a typo) and [11093-13698].

Like

• #### Jim Randell 11:16 am on 1 January 2023 Permalink | Reply

Thanks. Yes, the upper bound should be 13698.

Like

• #### Tony Smith 2:17 pm on 1 January 2023 Permalink | Reply

The only squares with odd penultimate digits have last digit 6.

Like

• #### Jim Randell 2:21 pm on 1 January 2023 Permalink | Reply

Neat. So we only need to check 9 cases:

```check(irange(356, 436, step=10))
```

Like

• #### Frits 3:25 pm on 1 January 2023 Permalink | Reply

@Jim, the check(irange(354, 444), step=10) is still needed.

Like

• #### Jim Randell 9:19 pm on 1 January 2023 Permalink | Reply

Right. Still, it is only 19 cases to check. Easy enough to do on a pocket calculator.

Like

• #### Jim Randell 2:10 pm on 2 January 2023 Permalink | Reply

Here is a version that uses less brute force (and less analysis).

The final two digits of the square number depend only on the final two digits of its root, so we can consider possible values for these 2 digits, and find those that give acceptable final two digits of the square. The final digit must corresponding to the digit length of the square, and then penultimate digit must be odd.

We then know the length of the square, final two digits and the leading digit must be a divisor of the penultimate digit, so we can consider possible roots that give the required conditions.

In the end we only need to apply the remaining tests on a handful of values.

This Python program runs in 51ms. (Internal runtime is 368µs).

Run: [ @replit ]

```from enigma import (irange, inf, sq, nsplit, sqrt, ceil, printf)

# is <x> a (proper) multiple of <n>?
is_multiple = lambda n, x: (x > n > 0 and x % n == 0)

# consider final 2 digits of the root of the perfect square
for i in irange(0, 99):
# and calculate the final 2 digits of the square
(y, z) = nsplit(sq(i), 2)
# y must be odd
if y % 2 != 1: continue
# z counts the total number of digits, which cannot be less than 5
if z < 5: continue
# y is a multiple of the leading digit (a)
for a in irange(1, y // 2):
if y % a != 0: continue
# consider possible roots
lo = ceil(sqrt(a * pow(10, z - 1)) - i, 100)
for j in irange(lo, inf, step=100):
n = sq(i + j)
ds = nsplit(n)
# there must be z digits
if len(ds) < z: continue
if len(ds) > z: break
if ds[0] < a: continue
if ds[0] > a: break
# there must be a 0 digit
if 0 not in ds: continue
# each digit must be different
if len(set(ds)) != z: continue
# 2nd and 3rd digits must be multiples of the 1st
if not (is_multiple(a, ds[1]) and is_multiple(a, ds[2])): continue
# output solution
printf("n = {n} [{r}^2]", r=i + j)
```

Liked by 1 person

• #### GeoffR 10:25 am on 31 December 2022 Permalink | Reply

```# check 5 - 9 digit square numbers
sq = [x * x for x in range(100, 31622)]

for n in sq:
# check the number of digits are all different
if len(str(n)) == len(set(str(n))):
n_str = str(n)

# check last-but-one digit is odd
# ... and one of the digits is zero after the third digit
if int(n_str[-2]) % 2 == 1 and '0' in n_str[2:]:
# check 2nd and third digits are a multiple of the 1st digit
if int(n_str[1]) % int(n_str[0]) == 0:
if int(n_str[2]) % int(n_str[0]) == 0:

# check last-but-one digit is a multiple of the 1st digit
if int(n_str[-2]) % int(n_str[0]) == 0:
# check last digit is length of number dialled
if int(n_str[-1]) == len(str(n)):
print(f"Number dialled was {n}.")

```

Like

• #### GeoffR 11:32 am on 2 January 2023 Permalink | Reply

This solution uses previous postings in that the telephone number is six or nine digits long and the possible ranges of square values.

```from enigma import nsplit, all_different

# check six digit phone numbers (abcdef)
n = 353

while n < 445:
n += 1
n1 = n * n  # potential square tel no.
a, b, c, d, e, f = nsplit(n1)

# teaser digit conditions
if f == 6 and d == 0 and e % 2 == 1:
if all_different(a, b, c, d, e, f):
# 2nd, 3rd and penultimate digits
#...are multiples of 1st digit
if all(x % a == 0 for x in (b, c, e)):
print(f"Martha dialled {n1}.")
break

# check nine digit phone numbers (abcdefghi)
m = 11092

while m < 13699:
m += 1
m1 = m * m  # potential square tel no.
a, b, c, d, e, f, g, h, i = nsplit(m1)

# teaser digit conditions
if i == 9 and 0 in (d, e, f, g) and h % 2 == 1:
if all_different(a, b, c, d, e, f, g, h, i):
# 2nd, 3rd and penultimate digits
# ...are multiples of 1st digit
if all(x % a == 0 for x in (b, c, h)):
print(f"Martha dialled {m1}.")
break

```

Like

• #### GeoffR 5:20 pm on 2 January 2023 Permalink | Reply

This program checks for a 6-digit solution only.
No 9-digit solution was found in previous programs.

```from enigma import is_square
D, F = 0, 6  # values fixed by teaser conditions
for A in range(1, 10):
for B in range(1, 10):
if B == A:continue
if B % A != 0:continue
for C in range(1, 10):
if C in (A, B):continue
if C % A != 0:continue
for  E in range(1, 10):
if E in (A,B,C,F):continue
if E % 2 != 1 or E % A != 0: continue
num = A * 10**5 + B * 10**4 + C * 10**3 + E*10 + F
if num // 100 % 10 != D:continue
if not is_square(num):continue
print(f"Martha dialled {num}.")
```

Like

## Teaser 2611: Simple arithmetic

From The Sunday Times, 7th October 2012 [link]

George and Martha are teaching their great-grandchildren some simple arithmetic. “If you add two thirties to four tens you get a hundred”, George was saying, and he wrote it like this:

“Strangely”, added Martha, there are nine different letters there, and if you allow each letter to stand for a different digit, there is a unique sum which works”.

Which digit would be missing?

[teaser2611]

• #### Jim Randell 8:40 am on 10 November 2022 Permalink | Reply

We can use the [[ `SubstitutedExpression.split_sum()` ]] solver from the enigma.py library to solve this puzzle.

The following run file executes in 58ms. (Internal runtime is 4.74ms).

Run: [ @replit ]

```from enigma import (SubstitutedExpression, irange, diff, join, printf)

# construct the alphametic sum
p = SubstitutedExpression.split_sum(
["THIRTY"] * 2 + ["TEN"] * 4, "HUNDRED",
template="(2 * {THIRTY} + 4 * {TEN} = {HUNDRED})",
)

# solve the puzzle, and output unused digit(s)
for s in p.solve():
ds = diff(irange(0, 9), s.values())
# output solution
printf("-> unused digits = {ds}", ds=join(ds, sep=", "))
```

Solution: The missing digit is 7.

Like

• #### GeoffR 11:40 am on 10 November 2022 Permalink | Reply

```
% A Solution in MiniZinc
include "globals.mzn";

%          T H I R T Y
%          T H I R T Y
%                T E N
%                T E N
%                T E N
%                T E N
%        -------------
%        H U N D R E D
%        -------------

set of int: INT = 0..9;
var INT: T; var INT: H; var INT: I;
var INT: R; var INT: Y; var INT: E;
var INT: N; var INT: U; var INT: D;

constraint T > 0 /\ H > 0;
constraint all_different( [T,H,I,R,Y,E,N,U,D]);

% Carry digits from RH end
var 0..6:c1; var 0..6:c2; var 0..6:c3;
var 0..1:c4; var 0..1:c5; var 0..1:c6;

% Adding digits in columns, with carry digits from RH end of sum
constraint D == (4*N + 2*Y) mod 10 /\ c1 == (4*N + 2*Y) div 10;
constraint E == (c1 + 4*E + 2*T) mod 10 /\ c2 == (c1 + 4*E + 2*T) div 10;
constraint R == (c2 + 4*T + 2*R) mod 10 /\ c3 == (c2 + 4*T + 2*R) div 10;
constraint D == (c3 + 2*I) mod 10 /\ c4 == (c3 + 2*I) div 10;
constraint N == (c4 + 2*H) mod 10 /\ c5 == (c4 + 2*H) div 10;
constraint U == (c5 + 2*T) mod 10 /\ c6 == (c5 + 2*T) div 10;
constraint H == c6;

solve satisfy;

output ["[T,H,I,R,Y,E,N,U,D] = " ++ show([T,H,I,R,Y,E,N,U,D]) ];
% [T, H, I, R, Y, E, N, U, D] =
% [9, 1, 5, 2, 6, 0, 3, 8, 4]
% ----------
% ==========
% By inspection, missing digit = 7.
% TEN = 903, THIRTY = 915296, HUNDRED = 1834204.

```

Like

• #### GeoffR 10:25 pm on 10 November 2022 Permalink | Reply

```
% A Solution in MiniZinc
include "globals.mzn";

%          T H I R T Y
%          T H I R T Y
%                T E N
%                T E N
%                T E N
%                T E N
%        -------------
%        H U N D R E D
%        -------------

set of int: INT = 0..9;
var INT: T; var INT: H; var INT: I;
var INT: R; var INT: Y; var INT: E;
var INT: N; var INT: U; var INT: D;

constraint T > 0 /\ H > 0;
constraint all_different( [T,H,I,R,Y,E,N,U,D]);

var 100..999:TEN = 100*T + 10*E + N;
var 100000..999999:THIRTY = 100000*T + 10000*H + 1000*I + 100*R + 10*T + Y;
var 1000000..9999999:HUNDRED = 1000000*H + 100000*U + 10000*N + 1000*D + 100*R + 10*E + D;

constraint 2 * THIRTY + 4 * TEN == HUNDRED;

solve satisfy;

output [ "T,H,I,R,Y,E,N,U,D] = " ++ show( [T,H,I,R,Y,E,N,U,D] ) ];

% [T, H, I, R, Y, E, N ,U, D] =
% [9, 1, 5, 2, 6, 0, 3, 8, 4]
% time elapsed: 0.17 s
% ----------
% ==========
% By inspection, the missing digit is 7.

```

Like

## Teaser 2746: Five finger exercise

George and Martha have a five-figure code for their burglar alarm. George commented that the three-figure number formed by the first three digits of the code equalled the sum of the cubes of those first three digits.

Martha added that the three-figure number formed by the last three digits of the code equalled the sum of the factorials of those three digits. (She had to remind George what a factorial was — he remembered once she had pointed out that the factorial of 4 was 4×3×2×1 = 24).

What is their code?

This puzzle was not included in the book The Sunday Times Brain Teasers Book 1 (2019).

This completes the archive of Teaser puzzles originally published in 2015. There is a complete archive of puzzles from 2015 – present available on S2T2, as wall as many older puzzles going back to 1949.

[teaser2746]

• #### Jim Randell 10:19 am on 20 October 2022 Permalink | Reply

We can use the [[ `SubstitutedExpression` ]] solver from the enigma.py library to solve this puzzle.

The following run file executes in 63ms. (The internal runtime of the generated program is 424µs).

Run: [ @replit ]

```#! python3 -m enigma -r

SubstitutedExpression

--distinct=""

"cb(A) + cb(B) + cb(C) = ABC"
"factorial(C) + factorial(D) + factorial(E) = CDE"
```

Solution: The code is: 37145.

And we have:

3³ + 7³ + 1³ = 371
1! + 4! + 5! = 145

Although not a condition of the puzzle, it turns out that the digits in the code are all different.

Like

• #### GeoffR 10:47 am on 20 October 2022 Permalink | Reply

```from itertools import permutations
from enigma import factorial as fact

for p1 in permutations(range(1, 10), 5):
A,B,C,D,E = p1
if A**3 + B**3 + C**3 == 100*A + 10*B + C:
if fact(C) + fact(D) + fact(E) == 100*C + 10*D + E:
code = 10000*A + 1000*B + 100*C + 10*D + E
print(f"Code is {code}.")

# Code is 37145.

```

Like

## Teaser 2737: Pinpoint accuracy

George and Martha’s bank PIN is an odd four-figure number. George did some calculations and wrote down three numbers: the first was the sum of the four digits in the PIN; the second was the average of the four digits; and the third was the product of the four digits.

Then Martha multiplied these three numbers together and was surprised that the answer equalled the original PIN.

What is their PIN?

This puzzle was not included in the book The Sunday Times Brain Teasers Book 1 (2019).

[teaser2737]

• #### Jim Randell 8:05 am on 13 October 2022 Permalink | Reply

None of the digits can be 0, as then the product of the digits would also be 0.

We can use the [[ `SubstitutedExpression` ]] solver from the enigma.py library to solve this puzzle.

The following run file executes in 65ms. (Internal runtime of the generated code is 1.1ms)

Run: [ @replit ]

```#! python3 -m enigma -r

SubstitutedExpression

--distinct=""
--digits="1-9"

# The following multiplied together give the value of the PIN
# (i) the sum of the digits;
# (ii) the mean of the digits (= (i) / 4);
# (iii) the product of the digits
"sq(A + B + C + D) * (A * B * C * D) == 4 * ABCD"

# the PIN is odd
"D % 2 = 1"
```

Solution: The PIN is: 1715.

Like

• #### GeoffR 12:16 pm on 13 October 2022 Permalink | Reply

```% A Solution in MiniZinc
include "globals.mzn";

var 1..9:A; var 1..9:B; var 1..9:C; var 1..9:D;
constraint D mod 2 == 1; % PIN number is odd

var 1000..9999:PIN = 1000*A + 100*B + 10*C + D;

% Num 1the sum of the four digits in the PIN
var 4..36:Num1 = A + B + C + D;

var 4..36: Num2; %  average = Num2 / 4
constraint Num2 == A + B + C + D;

% Num3 was the product of the four digits
var 1..6561: Num3 == A * B * C * D ; % UB = 9^4

% Martha multiplied these three numbers together
constraint 4 * PIN == Num1 * Num2 * Num3;

solve satisfy;

output[ "PIN = " ++ show(PIN) ];

% PIN = 1715
% ----------
% ==========

```

Like

## Teaser 2754: Family history

Three of George’s relatives who were born in different years of the 20th century shared the same birthday. Writing these in the form D/M/Y with just two digits for the year, he tells Martha that: in one case D divided by M, when expressed as a percentage, is Y; in another M is the average of D and Y; in the remaining one D raised to the power M equals Y. George then told Martha that knowing the day, D, would not enable her to work out the three dates, but knowing any one of the three years would enable her to work out all three dates.

What is the most recent of the three birth dates?

[teaser2754]

• #### Jim Randell 10:13 am on 9 June 2022 Permalink | Reply

The years are all in the 20th Century (i.e. 1901 – 2000).

This Python program runs in 57ms. (Internal runtime is 536µs).

Run: [ @replit ]

```from enigma import (
irange, product, div, seq_all_different as all_different,
filter_unique, unpack, intersect, printf
)

# generate possible dates
def generate():
# choose values for D and M
for (D, M) in product(irange(1, 31), irange(1, 12)):
if D > 28 and M == 2: continue
if D > 30 and M in {4, 6, 9, 11}: continue

# calculate the 3 (truncated) years
Ys = (div(100 * D, M), 2 * M - D, D ** M)
if any(y is None or y < 0 or y > 99 for y in Ys): continue
if not all_different(Ys): continue
yield (D, M, Ys)

# candidate solutions
ss = generate()

# knowing D does not let you work out the solution
ss = filter_unique(ss, unpack(lambda D, M, Ys: D)).non_unique

# but knowing _any_ of the years would let you work it out
fn = lambda k: unpack(lambda D, M, Ys: Ys[k])
ss = intersect(filter_unique(ss, fn(k)).unique for k in (0, 1, 2))

# output solution
for (D, M, Ys) in ss:
(Y1, Y2, Y3) = Ys
printf("D={D} M={M} -> Y1={Y1:02d} Y2={Y2:02d} Y3={Y3:02d}")
Y = max((2000 if y == 0 else y + 1900) for y in Ys)
printf("-> most recent (D/M/Y) = {D}/{M}/{Y}")
```

Solution: The most recent of the birth dates is: 2/5/40 (i.e. 2nd May 1940).

All birthdays are 2nd May, and the years are: 1908, 1932, 1940.

So we have:

2/5 = 40% → 1940
5 is the mean of 2 and 8 → 1908
2^5 = 32 → 1932

At the time of publication the most recent birthdays would be: 107th, 83rd, 75th.

There are 7 possible D/M pairs:

D=1 M=2 → Ys=(50, 3, 1)
D=1 M=4 → Ys=(25, 7, 1)
D=1 M=5 → Ys=(20, 9, 1)
D=1 M=10 → Ys=(10, 19, 1)
D=2 M=4 → Ys=(50, 6, 16)
D=2 M=5 → Ys=(40, 8, 32)
D=3 M=4 → Ys=(75, 5, 81)

The last of these is excluded as D is unique.

The D=2 M=5 case is the only one which can be uniquely determined given any of the Y values.

Like

## Teaser 3114: Colourful characters

George and Martha have recently taken a great-grandchild to a toddler’s birthday party. The youngsters like to traipse around over a pen with a large number of brightly coloured plastic balls. Actually there were 200 in total, some of red, yellow, blue and green. There were at least 30 but fewer than 70 of each colour, with the following properties:

Red = perfect square
Yellow = prime number
Blue = palindromic number
Green = divisible by three [different] single-digit prime numbers

George told Martha the above information and the number of red balls. Martha was then able to work out the numbers of each of the others.

How many of each colour were there?

[teaser3114]

• #### Jim Randell 5:18 pm on 27 May 2022 Permalink | Reply

i.e. the number of red balls is a perfect square; the number of yellow balls is prime; etc.

I required the number of green balls to be “divisible by exactly three different single-digit prime numbers”.

The following Python program runs in 54ms. (Internal run time is 310µs).

Run: [ @replit ]

```from enigma import (
irange, is_prime, is_square, is_npalindrome, product,
filter_unique, unpack, printf
)

# select candidate quantities [30, 69]
select = lambda fn: list(x for x in irange(30, 69) if fn(x))

# single digit primes
sdps = list(x for x in irange(0, 9) if is_prime(x))

# find the candidate quantities for each colour
Rs = select(is_square)
Ys = select(is_prime)
Bs = select(is_npalindrome)
Gs = select(lambda x: sum(x % d == 0 for d in sdps) == 3)

# generate possible (R, Y, B, G) combinations
def generate():
for qs in product(Rs, Ys, Bs, Gs):
if sum(qs) == 200:
yield qs

# find combinations unique by the number of reds
reds = unpack(lambda R, Y, B, G: R)
for (R, Y, B, G) in filter_unique(generate(), reds).unique:
printf("R={R} Y={Y} B={B} G={G}")
```

Solution: The numbers of balls are: Red = 36, Yellow = 67, Blue = 55, Green = 42.

Manually:

There are only a few options for each colour:

Red = (36, 49, 64)
Yellow = (31, 37, 41, 43, 47, 53, 59, 61, 67)
Blue = (33, 44, 55, 66)
Green = (30, 42, 60)

And we want combinations of these that sum to 200. Note that Yellow (prime) is always odd, so the sum of the other three must also be odd – Green is always even, so Red and Blue must be one odd and one even.

We quickly find there are 5 candidate solutions:

R=36 B=55 G=42 Y=67
R=49 B=44 G=60 Y=47
R=49 B=66 G=42 Y=43
R=64 B=33 G=42 Y=61
R=64 B=33 G=60 Y=43

And only R=36 give a unique set of values.

Like

• #### Frits 10:37 am on 28 May 2022 Permalink | Reply

@Jim, I would have probably chosen a different alias name for the itertools cartesian product as using the name product in combination with numbers is ambiguous (to me).

Like

• #### Jim Randell 11:06 am on 28 May 2022 Permalink | Reply

@Frits: A long time ago there used to have a `product()` function in enigma.py to calculate the product of a sequence of numbers.

But I renamed it `multiply()` to avoid confusion with `itertools.product()` (which is a useful function in solving puzzles).

Python 3.8 added a similar function to `multiply()` as `math.prod()`.

Like

• #### Jim Randell 11:50 am on 10 July 2022 Permalink | Reply

@Frits: I’ve added the [[ `cproduct()` ]] function to the enigma.py library. Which is an unpacked version of the [[ `itertools.product()` ]] function.

It makes it neater to make a Cartesian product from a generator (which is quite a common occurrence in puzzles):

```# using itertools.product
product(*(<generator>))
# using cproduct
cproduct(<generator>)
```

You can also use it for a fixed list of sets like this:

```# using itertools.product
product(As, Bs, Cs)
# using cproduct
cproduct([As, Bs, Cs])
```

Like

• #### GeoffR 6:29 pm on 27 May 2022 Permalink | Reply

Multiple output configuration produces five potential solutions, but only one of these solutions has a unique number of red balls, which gives the answer.

```
% A Solution in MiniZinc
include "globals.mzn";

% Red, Yellow, Blue and Green coloured ball numbers
var 30..69:R; var 30..69:Y; var 30..69:B; var 30..69:G;

constraint R + Y + B + G == 200;

predicate is_sq(var int: y) =
exists(z in 1..ceil(sqrt(int2float(ub(y))))) (z*z = y);

% R is a square number
constraint is_sq(R);

predicate is_prime(var int: x) =
x > 1 /\ forall(i in 2..1 + ceil(sqrt(int2float(ub(x)))))
((i < x) -> (x mod i > 0));

% Y is a prime number
constraint is_prime(Y);

% B is a 2-digit palindromic number
constraint B div 10 == B mod 10;

% G has 3 single digit prime divisors i.e three from 2, 3, 5, 7
constraint sum( [bool2int(G mod 2 == 0), bool2int(G mod 3 == 0),
bool2int(G mod 5 == 0), bool2int(G mod 7 == 0)] ) == 3;

solve satisfy;

output [ "[R,Y,B,G ]= " ++ show( [R,Y,B,G ]) ];

```

Like

• #### Frits 6:52 pm on 27 May 2022 Permalink | Reply

```
from enigma import SubstitutedExpression

# return entry where column <col> is unique
def unique_col(seq, col=0):
d = dict()
for s in seq:
d[s[col]] = s[col] in d

return [s for s in seq if not d[s[col]]]

# the alphametic puzzle
p = SubstitutedExpression(
[
# Red = perfect square
"is_square(RD)",
# Yellow = prime number
"is_prime(YW)",
# Blue = palindromic number
"BE in {33, 44, 55, 66}",

# there were 200 in total
"200 - RD - YW - BE = GN",
# Green = divisible by three single-digit prime numbers
"sum(GN % p == 0 for p in [2, 3, 5, 7]) == 3",

],
d2i=dict([(k, "RYBG") for k in range(3)] +
[(k, "RYBG") for k in range(7, 10)]),
distinct="",
verbose=0,
)

colors = ["Red", "Yellow", "Blue", "Green"]
# get unique answers for number of red balls
uniq = unique_col([y for _, y in p.solve()])
print(*list(zip(colors, uniq[0])))
```

Like

• #### GeoffR 9:01 am on 28 May 2022 Permalink | Reply

Separate research found three possible values for Green between 30 and 69:

G = 30, prime factors = 2 * 3 * 5
G = 42, prime factors = 2 * 3 * 7
G = 60, prime factors = 2 * 2 * 3 * 5

```
from collections import defaultdict
COL = defaultdict(list)

# Using R = Red, Y = Yellow, B = Blue, G = Green
for R in (36, 49, 64):  # Squares from 30..69
# Primes between 30 and 69
for Y in (31, 37, 41, 43, 47, 53, 59, 61, 67):
# Palindromes between 30 and 69
for B in (33, 44, 55, 66):
for G in (30, 42, 60):
if R + Y + B + G != 200:
continue
COL[R] += [(R, Y, B, G)]

for k, v in COL.items():
if len(v) == 1:
print(f"R={v[0][0]}, Y={v[0][1]}, B={v[0][2]}, G={v[0][3]}")

```

Like

• #### Frits 10:12 am on 28 May 2022 Permalink | Reply

No imports, using methods from Brian and Jim.

```
# pick one value from each entry of a <k>-dimensional list <ns>
# so that all elements sum up to <t>
def pickOneFromEach(k, ns, t, s=[]):
if k == 1:
# does the remainder occur in the first list?
if t in ns[0]:
yield s + [t]
else:
for n in ns[k-1]:
yield from pickOneFromEach(k - 1, ns, t - n, s + [n])

sqs = [x * x for x in range(6, 9)]
# use set() as it will be only used for lookups
prms = set(x for x in range(31, 70, 2) if all(x % i for i in [2, 3, 5, 7]))
pals = [11 * x for x in range(3, 7)]
divs = [x for x in range(30, 70) if sum(x % i == 0 for i in [2, 3, 5, 7]) == 3]

# place the list with the most elements up front and squares at the end
mlst = [prms, divs, pals, sqs]

seen_once = dict()
# get unique answers for number of red balls
for x in pickOneFromEach(4, mlst, 200):
seen_once[x[0]] = x if x[0] not in seen_once else []

colors = ["Red", "Blue", "Green", "Yellow"]
for k, vs in seen_once.items():
if vs:
print(*list(zip(colors, vs)))
```

Like

## Teaser 2857: Significant errors

From The Sunday Times, 25th June 2017 [link]

Last year George and Martha were going to visit one of their daughters. Her house number was a two-figure number but unfortunately Martha wrote the number incorrectly by making the first digit less than it should be. When George discovered the error he commented that the incorrect number was a whole number percentage of the correct one. If you knew that percentage then you should be able to work out their daughter’s house number.

Then the daughter moved to a different two-figure house number, Martha again wrote the number incorrectly by making the first digit less than it should be, and again the incorrect number was a whole number percentage of the correct one. If you knew that percentage then you should be able to work out their daughter’s new house number.

What was the daughter’s original house number, and what is the new one?

[teaser2857]

• #### Jim Randell 8:46 am on 21 April 2022 Permalink | Reply

This Python program collects possible (house-number, wrong-number, percentage-reduction) values, and then uses the [[ `filter_unique()` ]] function from the enigma.py library to find the required values for the first and second house numbers.

It runs in 55ms. (Internal runtime is 333µs).

Run: [ @replit ]

```from enigma import irange, div, filter_unique, unpack, printf

# record (n, w, p) results
rs = list()

# consider two digit house numbers
for n in irange(20, 99):
# consider different numbers with the first digit less than the
# correct digit, but the second digit is correct
for w in irange(10 + (n % 10), n - 1, step=10):
# calculate the percentage w / n
p = div(100 * w, n)
if p is None: continue
rs.append((n, w, p))

# if you knew the percentage you would know the correct house number
fn_n = unpack(lambda n, w, p: n)
fn_p = unpack(lambda n, w, p: p)
for (n1, w1, p1) in filter_unique(rs, fn_p, fn_n).unique:
printf("p1={p1}% -> n1={n1} w1={w1}")

# look for results with a different house number
rs1 = filter(unpack(lambda n2, w2, p2: n2 != n1), rs)
for (n2, w2, p2) in filter_unique(rs1, fn_p, fn_n).unique:
printf("  p2={p2}% -> n2={n2} w2={w2}")
printf()
```

Solution: The first house number was 50. The second house number was 75.

There are two possible scenarios:

Daughter’s first house was 50, but she wrote 20 (= 40% of 50).
Daughter’s second house was 75, but she wrote 15 (= 20% of 75).

Daughter’s first house was 50, but she wrote 40 (= 80% of 50).
Daughter’s second house was 75, but she wrote 15 (= 20% of 75).

But in both cases the first house number is 50 and the second house number is 75.

Here are the 15 possible (house number, wrong number) pairs, grouped by percentage:

20%: (50 → 10) (75 → 15)
25%: (40 → 10) (80 → 20)
40%: (50 → 20)
50%: (20 → 10) (40 → 20) (60 → 30) (80 → 40)
60%: (25 → 15) (50 → 30) (75 → 45)
75%: (40 → 30) (80 → 60)
80%: (50 → 40)

From which we see the only values with a unique percentage are:

40%: (50 → 20)
80%: (50 → 40)

Both cases give a first house number of 50.

If we remove pairs with a first house number of 50 from those listed above we get:

20%: (75 → 15)
25%: (40 → 10) (80 → 20)
50%: (20 → 10) (40 → 20) (60 → 30) (80 → 40)
60%: (25 → 15) (75 → 45)
75%: (40 → 30) (80 → 60)

And we see there is only one value with a unique percentage:

20%: (75 → 15)

And so the second house number is 75.

Like

## Teaser 2879: Blood line

From The Sunday Times, 26th November 2017 [link]

Patients numbered 1 to 99 were waiting for a blood test. George’s and Martha’s numbers were consecutive. Patients were called in [a] random order to one of the available cubicles numbered 1 to 9. The nurse in each cubicle took a fixed whole number of minutes to do the test, but that time varied from cubicle to cubicle. All cubicles started at 10am and they all finished together before 5pm on the same day. Amazingly, it turned out that each patient’s cubicle number was the highest digit that divided into their patient number. George noted that, when he was called, the session had been running for a number of minutes whose digits [when] added to[gether gave] his cubicle number. Martha noted that the same was true for her.

What were their patient numbers?

Unfortunately this puzzle has multiple solutions (apparently introduced by the editing process for puzzles at the paper).

This puzzle was not included in the published collection of puzzles The Sunday Times Brainteasers Book 1 (2019).

[teaser2879]

• #### Jim Randell 9:31 am on 27 January 2022 Permalink | Reply

The following program finds 5 possible pairs of patient numbers that satisfy the conditions.

We know which cubicle each patient is to visit, so we can form them into queues for that cubicle.

The session lasts for less than 7 hours = 420 minutes, and the cubicles finish at the same time. So the total length of the session must be a multiple of the length of each queue. (And it turns out there is only one possible duration).

We can now calculate the time taken for each cubicle, and look for cubicles that have elapsed call times with a digit sum that is the same as the cubicle number.

Then we can look for consecutive patient numbers that are called to these cubicles, and these give us possible patient numbers for Martha and George.

The following Python program runs in 50ms.

Run: [ @replit ]

```from enigma import irange, peek, group, mlcm, dsum, tuples, union, printf

# map patients to queue number
ns = irange(1, 99)
queue = lambda n: peek(d for d in irange(9, 1, step=-1) if n % d == 0)
n2q = dict((n, queue(n)) for n in ns)

# form the queues
qs = group(ns, by=(lambda n: n2q[n]))

# consider the total length of the session < 7h = 420m
m = mlcm(*(len(v) for v in qs.values()))
for t in irange(m, 419, step=m):
printf("duration = {t} mins")

# find cubicles with elapsed call times that sum to their digit
ks = set()
for (k, vs) in qs.items():
x = t // len(vs)
for s in irange(x, t - x, step=x):
if dsum(s) == k:
printf("queue {k}; {x} mins/test; call at {s} mins")

# find consecutive numbers for patients in queues in ks
for (a, b) in tuples(sorted(union(qs[k] for k in ks)), 2):
if b == a + 1:
printf("({a}, {b}) -> ({qa}, {qb})", qa=n2q[a], qb=n2q[b])
```

Solution: The are 5 possible pairs of patient numbers for Martha and George: (26, 27), (44, 45), (45, 46), (62, 63), (81, 82).

After constructing the queues for each of the digits 1-9, we see that the only possible duration of the session is 264 minutes, and there are 6 possible times when a patient could be called such that the digit sum of the elapsed number of minutes is the same as the cubicle number.

called at 72 minutes to cubicle 9
called at 110 minutes to cubicle 2
called at 132 minutes to cubicle 6
called at 144 minutes to cubicle 9
called at 216 minutes to cubicle 9
called at 220 minutes to cubicle 4

This means that we can have the following consecutive numbers for George and Martha:

26 & 27 → called to cubicle 2 (after 110 minutes) and cubicle 9 (after 72, 144, or 216 minutes)
44 & 45 → called to cubicle 4 (after 220 minutes) and cubicle 9 (after 72, 144, or 216 minutes)
45 & 46 → called to cubicle 9 (after 72, 144, or 216 minutes) and cubicle 2 (after 110 minutes)
62 & 63 → called to cubicle 2 (after 110 minutes) and cubicle 9 (after 72, 144, or 216 minutes)
81 & 82 → called to cubicle 9 (after 72, 144, or 216 minutes) and cubicle 2 (after 110 minutes)

The additional constraint that “George and Martha were called less than half an hour apart” would narrow these down to a single solution:

44 & 45 → called to cubicle 4 (after 220 minutes) and cubicle 9 (after 216 minutes)

Like

## Teaser 3094: There’s always next year

George and Martha annually examine around 500 candidates (give or take 5%). It is board policy to pass about a third of the entrants but the precise recent percentage pass rates were as above.

The number of entrants in each year up to 2021 was different as was the number of successful candidates. George told Martha of the number of entries for 2022 (different again) and Martha calculated that, if X were to be once again a whole number (also different again but within the above range), the total number of successful candidates over the five-year period would be a perfect square.

How many entries are there for 2022 and how many successful candidates did Martha calculate for 2022?

[teaser3094]

• #### Jim Randell 5:08 pm on 7 January 2022 Permalink | Reply

I considered total candidates for each year in the range [475, 525], and by allowing the (integer) percentages to be in the range [30, 36] I was able to find a unique solution.

This Python program runs in 53ms.

Run: [ @replit ]

```from enigma import (
divc, divf, div, irange, cproduct, unzip,
seq_all_different, is_square, printf
)

# given pass rates (percentages)
rates = [30, 32, 35, 36]

# find viable "<n> of <t>" pairs for percentages 30 - 36
pairs = dict()
for x in irange(30, 36):
pairs[x] = list()
for n in irange(divc(475 * x, 100), divf(525 * x, 100)):
t = div(100 * n, x)
if t is not None:
pairs[x].append((n, t))

# consider possible (n, t) pairs for the given years
for nts in cproduct(pairs[x] for x in rates):
(ns, ts) = unzip(nts)
if not (seq_all_different(ns) and seq_all_different(ts)): continue
nsum = sum(ns)

# consider possible (n, t) pairs for 2022
for (k, vs) in pairs.items():
if k in rates: continue
for (n, t) in vs:
if n in ns or t in ts: continue
# is the total number of n's a square?
if is_square(n + nsum):
printf("k={k}% -> {n} of {t} [ns={ns} ts={ts}]")
```

Solution: There were 500 entries for 2022. Martha’s calculation was for 165 successful candidates.

Like

• #### GeoffR 8:29 pm on 7 January 2022 Permalink | Reply

```% A Solution in MiniZinc
include "globals.mzn";

predicate is_sq(var int: y) =
exists(z in 1..ceil(sqrt(int2float(ub(y))))) (z*z = y );

% Total entrants for each year & given pass rates
var 475..525:Y2018;  %Pass % = 30
var 475..525:Y2019;  %Pass % = 32
var 475..525:Y2020;  %Pass % = 35
var 475..525:Y2021;  %Pass % = 36

var 475..525:Y2022;
var 30..36:P5;  % Per Cent pass rate for Y2022

% total entrants, successful candidates, pass rates are all different
constraint all_different( [Y2018, Y2019, Y2020, Y2021, Y2022]);
constraint all_different ([SC2018, SC2019, SC2020, SC2021, SC2022]);
constraint all_different([30, 32, 35, 36, P5]);

% Total passes for each year
% LB = 0.3 * 475 = 142, UB = 0.36 * 525 = 189
var 142..189:SC2018; var 142..189:SC2019; var 142..189:SC2020;
var 142..189:SC2021; var 142..189:SC2022;

% calculate successful candidates for each year
constraint 100 * SC2018 == 30 * Y2018;
constraint 100 * SC2019 == 32 * Y2019;
constraint 100 * SC2020 == 35 * Y2020;
constraint 100 * SC2021 == 36 * Y2021;
constraint 100 * SC2022 == P5 * Y2022;

% total successful candidates for years (2018 - 2022) is a square
constraint is_sq(SC2018 + SC2019 + SC2020 + SC2021 + SC2022);

solve satisfy;

output [ "Successful candidates for 2022 = " ++ show(SC2022) ++ "\n"
++ "Total entrants for 2022 = " ++ show(Y2022)
++ "\n"  ++ "2022 Pass % = " ++ show(P5)];

```

Like

## Teaser 2830: Time for Christmas

For Christmas George has bought Martha a novelty digital 24-hour clock. It has an eight-digit display forming four two-digit numbers. The first three of these two-digit numbers are very conventional – the hours, the minutes and the seconds. However, the final two-digit display shows the sum of the first six displayed digits!

On two occasions today all eight digits displayed were different and three of the four two-digit numbers were perfect squares. Between those two occasions there was a time when the eight digits displayed were again all different, but this time the sum of the eight digits was a perfect square!

What was the eight-digit display at that in-between time?

[teaser2830]

• #### Jim Randell 10:12 am on 12 October 2021 Permalink | Reply

If we accept that there are only “two occasions” in any given day, then we don’t need to consider all the times, just look until we find the second condition (p2) occurring between the two occurrences of the first condition (p1).

This code stops when it finds the second occurrence of the first condition and runs in 61ms.

Run: [ @replit ]

```from enigma import (irange, flatten, product, printf)

# output format: <hour>:<minute>:<second>:<sum> [<state>]
fmt = "{h:02d}:{m:02d}:{s:02d}:{t:02d} [{state}]"

# 2 digit squares
squares = set(i * i for i in irange(0, 8))

# initial state
state = 0

# consider times in order
for (h, m, s) in product(irange(0, 23), irange(0, 59), irange(0, 59)):
# collect digits
digits = flatten((divmod(x, 10) for x in (h, m, s)), fn=list)
t = sum(digits)
digits.extend(divmod(t, 10))
# all digits are different
if len(set(digits)) != 8: continue

# mark special states
# p1 = "three of the four two digits numbers are perfect squares"
p1 = (len(squares.intersection((h, m, s, t))) == 3)
# p2 = "the sum of all 8 digits is a perfect square"
p2 = (sum(digits) in squares)
if not (p1 or p2): continue

# if we're in the initial state, wait until we see a p1
if state == 0:
if p1:
printf(fmt, state='first')
state = 1

# if we've seen the first p1
elif state == 1:
# look for the second p1
if p1:
printf(fmt, state='second')
# and we are done
break
# or for an intermediate p2
elif p2:
printf(fmt, state='in-between')
```

Solution: The display at the in-between time was 01:48:59:27.

The times are:

01:38:49:25 [first]
01:48:59:27 [in-between]
01:49:38:25 [second]

Like

• #### Jim Olson 5:24 pm on 13 October 2021 Permalink | Reply

Am I missing something but the middle digits sum to 54 which is not a perfect square.

Like

• #### Jim Randell 5:32 pm on 13 October 2021 Permalink | Reply

At the in-between time the sum of the 8 digits is:

0+1+4+8+5+9+2+7 = 36 = 6²

Like

• #### Jim Olson 5:51 pm on 13 October 2021 Permalink | Reply

Thank you I was adding the number 27 instead of the digit sum of 9.

Like

## Teaser 3072: Dial M for Marriage

From The Sunday Times, 8th August 2021 [link]

George and Martha work in a town where phone numbers have seven digits. “That’s rare!”, commented George. “If you look at your work number and mine, both exhibit only four digits of the possible ten (0-9 inclusive), each appearing at least once. Furthermore, the number of possible phone numbers with that property has just four single-digit prime number factors (each raised to a power where necessary) and those four numbers are the ones in our phone numbers”.

“And that is not all!”, added Martha. “If you add up the digits in the two phone numbers you get a perfect number in both cases. Both have their highest digits first, working their way down to the lowest”.

[A perfect number equals the sum of its factors, e.g., 6 = 1 + 2 + 3].

What are two phone numbers?

[teaser3072]

• #### Jim Randell 5:43 pm on 6 August 2021 Permalink | Reply

This puzzle sounds more complicated than it is.

There are only 4 single digit primes (2, 3, 5, 7), so these must be digits of the phone numbers. And they must occur in the order 7*5*3*2*, where the * is zero or more repeats of the previous digit, to give 7 digits in total.

This Python program considers the possible phone numbers composed of these digits, and finds those with a digit sum that is a perfect number.

It runs in 51ms.

Run: [ @replit ]

```from enigma import (irange, divisors, cache, join, printf)

# decompose <t> into <k> positive integers
def decompose(t, k, ns=[]):
if k == 1:
yield ns + [t]
else:
k_ = k - 1
for n in irange(1, t - k_):
yield from decompose(t - n, k_, ns + [n])

# is a number perfect?
@cache
def is_perfect(n):
return sum(divisors(n)) == 2 * n

# find possible distributions of digits
for (m7, m5, m3, m2) in decompose(7, 4):
# the digits ...
ds = [7] * m7 + [5] * m5 + [3] * m3 + [2] * m2
# ... and their sum ...
t = sum(ds)
# ... is it perfect?
if is_perfect(t):
printf("{ds} -> {t}", ds=join(ds))
```

Solution: The phone numbers are 7553332 and 7753222.

Both numbers have a digit sum of 28, which is a perfect number (28 = 1 + 2 + 4 + 7 + 14).

For completeness:

There are 1764000 possible 7-digit phone numbers that consist of exactly 4 different digits. And we can factorise this as:

1764000 = (2^5)(3^2)(5^3)(7^2)

So it does indeed have a prime factorisation that consists of (positive) powers of the 4 single-digit prime numbers.

But this is not needed to solve the puzzle.

This number can be determined by calculation, or just counting (it takes a few seconds in PyPy):

```>>> icount(n for n in irange(0, 9999999) if len(set(nsplit(n, 7))) == 4)
1764000
```

But if you can’t wait that long (or you want to look at larger values) they can be calculated using a recurrence relation:

```from enigma import (cache, arg, printf)

# how many n-digit phone numbers consisting of k different digits?
@cache
def N(n, k):
if k == 0 or n < k: return 0
if k == 1: return 10
return k * N(n - 1, k) + (11 - k) * N(n - 1, k - 1)

n = arg(7, 0, int)
k = arg(4, 1, int)
printf("N({n}, {k}) = {r}", r=N(n, k))
```

I use this function in a “complete” solution, that calculates N(7, 4), and the single digit prime factors of it (and it ensures there are 4 of them), it then finds distributions of these prime digits that give a phone number with a perfect digit sum.

```from enigma import (decompose, divisors, prime_factor, flatten, join, cached, printf)

# how many n-digit phone numbers consisting of k different digits?
@cached
def _N(n, k, b):
if k == 0 or n < k: return 0
if k == 1: return b
return k * _N(n - 1, k, b) + (b + 1 - k) * _N(n - 1, k - 1, b)

N = lambda n, k, base=10: _N(n, k, base)

# is a number perfect?
@cache
def is_perfect(n):
return sum(divisors(n)) == 2 * n

# find number 7-digit phone numbers with 4 different digits
n = N(7, 4)

# determine the prime factorisation
fs = list(prime_factor(n))
printf("N(7, 4) = {n} -> {fs}")

# look for single digit primes
ps = list(p for (p, e) in fs if p < 10)
printf("primes = {ps}")
assert len(ps) == 4

# find possible distribution of the prime digits
for ns in decompose(7, 4, increasing=0, sep=0, min_v=1):
# the digits of the phone number
ds = flatten([d] * n for (d, n) in zip(ps, ns))
# and their sum
t = sum(ds)
# is it perfect?
if is_perfect(t):
ds.reverse()
printf("number = {ds} -> dsum = {t}", ds=join(ds))
```

Like

• #### Jim Randell 9:27 am on 7 August 2021 Permalink | Reply

Here’s an alternative (shorter) program. It starts by looking for possible values of the sum (there is only one candidate that is a perfect number), and then uses the [[ `express()` ]] function from the enigma.py library to determine possible combinations of 7 digits to achieve the sum. It runs in 49ms.

Run: [ @replit ]

```from enigma import irange, divisors, express, join, printf

# is a number perfect?
is_perfect = lambda n: sum(divisors(n)) == 2 * n

# the smallest possible sum is (2+3+5+7)+(2+2+2) = 23
# the largest  possible sum is (2+3+5+7)+(7+7+7) = 38
for t in irange(23, 38):
if not is_perfect(t): continue

# make the sum from the amounts
for ns in express(t, [2, 3, 5, 7], min_q=1):
if sum(ns) != 7: continue

# construct the phone number
ds = join(d * n for (d, n) in zip("7532", reversed(ns)))
printf("{ds} -> {t}")
```

Liked by 2 people

• #### GeoffR 12:37 pm on 7 August 2021 Permalink | Reply

Perfect numbers are 6, 28, 496, 8128, …
Only possible perfect number for sum of seven digits is 28
i.e. for seven digits containing 2, 3, 5 or 7.

A shorter version using “express” from enigma.py

```
from enigma import express

# list of potential telephone numbers
TN = list(express(28, [7, 5, 3, 2], min_q=1))

for t in TN:
if sum(t) == 7:
a, b, c, d  = t[0], t[1], t[2], t[3]
print('7'*a + '5'*b + '3'*c + '2'*d)

```

Like

• #### Jim Randell 2:22 pm on 7 August 2021 Permalink | Reply

Or, as a single expression:

```>>> list('7' * d + '5' * c + '3' * b + '2' * a for (a, b, c, d) in express(28, [2, 3, 5, 7], min_q=1) if a + b + c + d == 7)
['7553332', '7753222']
```

Like

• #### Frits 9:31 am on 8 August 2021 Permalink | Reply

Or:

```
>>> list('7' * (d + 1) + '5' * (c + 1) + '3' * (b + 1) + '2' * (a + 1) for (a, b, c, d) in express(11, [2, 3, 5, 7]) if a + b + c + d == 3)
```

Like

• #### GeoffR 8:16 pm on 6 August 2021 Permalink | Reply

```
from enigma import divisors, dsum, nsplit

tel_list = []

# Re-using Jim's function
def is_perfect(n):
return sum(divisors(n)) == 2 * n

def is_descending(n):
# 7-digit nos. only
a, b, c, d, e, f, g = nsplit(n)
if a >= b and b >= c and c >= d and d >= e \
and e >= f and f >= g:
return True
return False

# find 7-digit Tel. Nos. with specified digit pattern
for n in range(7532222, 7777533):
s = set(str(n))
if s == {'7', '5', '3', '2'}:
if is_descending(n) and is_perfect(dsum(n)):
tel_list.append(n)

if len(tel_list) == 2:
print(f"Two tel. nos. are {tel_list[0]} and {tel_list[1]}.")

```

Like

• #### GeoffR 4:26 pm on 7 August 2021 Permalink | Reply

Setting the output to multiple configurations gives the two telephone numbers.

```% A Solution in MiniZinc
include "globals.mzn";

% Both telephone numbers consist of four single digit primes
set of int: pr = {2, 3, 5, 7};

% 7 digits in telephone numbers
var pr: A; var pr: B; var pr: C; var pr: D;
var pr: E; var pr: F; var pr: G;

% Possible range of telephone numbers
var 7532222..7777533: TelNum = 1000000*A + 100000*B + 10000*C
+ 1000*D + 100*E + 10*F + G;

% Both telephone numbers include the digits 2, 3, 5 and 7
constraint {A, B, C, D, E, F, G} == {2, 3, 5, 7};

% 28 is only viable perfect number for the sum of seven digits
constraint A + B + C + D + E + F + G == 28;

% digits must not be in ascending order
constraint A >= B /\ B >= C /\ C >= D /\ D >= E
/\ E >= F /\ F >= G;

solve satisfy;

output ["Tel. No. = " ++ show(TelNum) ];

```

Like

• #### GeoffR 7:28 pm on 8 August 2021 Permalink | Reply

```Module Module1
' A Solution in Visual Basic 2019

Sub Main()
For a As Integer = 1 To 4
For b As Integer = 1 To 4
For c As Integer = 1 To 4
For d As Integer = 1 To 4

' tel. no.is 7 digits long
If (a + b + c + d = 7) Then
' tel digits sum to the perfect number 28
If (7 * a + 5 * b + 3 * c + 2 * d = 28) Then
' form tel. no.
Dim TelNo As String

TelNo = StrDup(a, CStr(7)) + StrDup(b, CStr(5)) +
StrDup(c, CStr(3)) + StrDup(d, CStr(2))
Console.WriteLine("Tel. No. is {0}", TelNo)
End If
End If

Next 'd Loop
Next 'c Loop
Next  'b loop
Next   'a loop

End Sub

End Module

```

Like

## Teaser 3065: Members of the jury

From The Sunday Times, 20th June 2021 [link]

A jury had twelve members, all with different ages (at least 20 but not more than 65), except that two were twins with a common age over 40. The average age was a prime number. A counsel objected to one of the members and he was replaced by another with the result that the average age was reduced to another prime number. Between the two juries, there were twelve different ages and they formed a progression with a common difference (e.g., 1, 4, 7, 10, 13, etc. or 6, 13, 20, 27, 34, etc.,). None of the individuals had a perfect square age, and the replacement jury still included both twins.

How old were the twins?

[teaser3065]

• #### Jim Randell 2:38 pm on 18 June 2021 Permalink | Reply

This Python program runs in 53ms.

Run: [ @replit ]

```from enigma import irange, inf, div, is_prime, printf

squares = set(i * i for i in irange(5, 8))  # disallowed square ages

# consider possible start ages
for a in irange(20, 54):
# and possible common differences
for d in irange(1, inf):
# the progression consisting of 12 ages
ns = list(irange(a, a + 11 * d, step=d))
if ns[-1] > 65: break
# there are no squares
if squares.intersection(ns): continue

# one of the 12 ages is the replacement age (y)
t = sum(ns)
for (i, y) in enumerate(ns):
# the ages of the original jury
js = ns[:i] + ns[i + 1:]
# duplicate one of them
for z in reversed(js):
# duplicate age is over 40
if z < 41: break
# and gives a prime mean age
m1 = div(t - y + z, 12)
if m1 is None or not is_prime(m1): continue

# replace one of the original ages x with y
for x in js[i:]:
if x == z: continue
# mean age of the new jury is a lower prime
m2 = div(t - x + z, 12)
if m2 is None or not is_prime(m2): continue

# output solution
printf("twins = {z} [{js} + {z}; avg={m1}; {x} -> {y}; avg={m2}]", js=tuple(js))
```

Solution: The twins are 41.

The sequence of ages for both juries are all those ages between 26 and 59 in steps of 3.

The ages of the original jury are:

26, 29, 32, 38, 41, 41, 44, 47, 50, 53, 56, 59; mean = 43

The 59 year old is then replaced by a 35 year old:

26, 29, 32, 35, 38, 41, 41, 44, 47, 50, 53, 56; mean = 41

One way to test your program is to remove the constraint that there are no squares. Without this condition you should find 10 different answers for the age of the twins.

Liked by 1 person

• #### Tony Brooke-Taylor 12:05 pm on 19 June 2021 Permalink | Reply

Similar routine but with a bit less trial and error, so marginally quicker

```
primes=list(SieveOfEratosthenes(65))#function left out for ease of reading
squares=[x**2 for x in range(4,9)]

for delta in range(1,5): #possible common differences
for a_min in range(20,66-11*delta): #consequential possible start ages
ages=[a_min+delta*i for i in range(12)] #sequence of 12 ages
if set(ages).intersection(squares):continue #no square ages

twins=[t for t in ages if t>40]#subset of possible ages of the twins
a_ave=a_min+11*delta/2#average of the 12 ages
min_ave = a_ave+(40-max(ages))/12#lowest possible average age of a jury
max_ave = a_ave+(max(ages)-min(ages))/12#highest possible average age of a jury
poss_aves = [p for p in primes if p>=min_ave and p<max_ave]
if len(poss_aves)<2:continue
#possible prime average ages for a jury, must be (at least) 2 of them

for twin in twins: #find twins' age by trial and error
rejects=[]
for poss_ave in poss_aves:
swapped=twin+(a_ave-poss_ave)*12#age of swapped juror relative to twins
if swapped>a_min+11*delta:break
if swapped >=20:rejects.append(swapped)
#reject impossible juror ages

if len(rejects)>1: #solution contains at least two swapped juror ages
print("The ages of the twins was",twin)
#happily there is one solution and it has exactly two swapped jurors

```

Liked by 1 person

• #### Jim Randell 10:20 am on 20 June 2021 Permalink | Reply

The [[ `Primes` ]] class in the enigma.py library implements a prime sieve, so you can use the following to avoid having to include the code in your program, but still posting runnable code.

```from enigma import Primes
primes = Primes(66)
```

And it might be worth placing longer comments on the line above the code, as horizontal space is limited in replies.

Like

• #### Jim Randell 10:57 am on 20 June 2021 Permalink | Reply

@Tony: It’s an interesting approach.

Here’s a version using a similar idea, but calculates the separation of the replacement/replaced pair in the progression from the difference between the prime means, and then looks for suitable candidates, from which the repeated age can be determined:

```from enigma import Primes, subsets, irange, inf, sq, div, divc, divf, printf

squares = set(map(sq, irange(5, 8)))  # disallowed square ages
primes = Primes(60)

# consider possible start ages
for a in irange(20, 54):
# and possible common differences
for d in irange(1, inf):
# the sequence of 12 ages
ns = list(irange(a, a + 11 * d, step=d))
if ns[-1] > 65: break
# there are no squares
if squares.intersection(ns): continue
t = sum(ns)

# consider possible mean ages (m2, m1)
m_min = divc(t + 41 - ns[-1], 12)
m_max = divf(t + ns[-1] - ns[0], 12)
for (m2, m1) in subsets(primes.irange(m_min, m_max), size=2):
# calculate separation between replaced and replacement
k = div(12 * (m1 - m2), d)
if k is None: continue

# consider possible replacement pairs (x = ns[j - k] replaces y = ns[j])
for j in irange(11, k, step=-1):
# calculate repeated age (z)
z = 12 * m2 + ns[j] - t
if z < 41: break
if z in ns and z != ns[j] and z != ns[j - k]:
# output solution
printf("twins = {z} [{ns}; {x} replaces {y}; avg: {m1} -> {m2}]", ns=tuple(ns), x=ns[j - k], y=ns[j])
```

There is only one candidate pair of prime ages, and only one of the potential replacement/replaced pairings gives a duplicate age greater than 40.

(And a bit more analysis fixes the values of the common difference, the mean ages, and the difference between the replaced and replacement ages).

Like

A nice approach, Tony, which I ‘stole’ here. For those who want to run your code, here is a one line replacement for line one:

```primes = {x for x in range(23, 63, 2) if all(x % p for p in {2, 3, 5, 7})}
```

Like

• #### GeoffR 1:27 pm on 20 June 2021 Permalink | Reply

Hi Tony,

I have re-formatted your code to PEP8, which can easily be done under the Wingware IDE for Python,
using Source/Reformatting from the main menu – hope you don’t mind, but it does make code much
easier to read and appreciate by others. Have also replaced end of line comments as separate comments, as suggested by Jim. An interesting solution.

```#primes = list(SieveOfEratosthenes(65))
# using Brian's replacement for line above
primes = {x for x in range(23, 63, 2)
if all(x % p for p in {2, 3, 5, 7})}
squares = [x**2 for x in range(4, 9)]

# possible common differences
for delta in range(1, 5):
# consequential possible start ages
for a_min in range(20, 66 - 11 * delta):
# sequence of 12 ages
ages = [a_min + delta * i for i in range(12)]
# no square ages
if set(ages).intersection(squares):
continue

# subset of possible ages of the twins
twins = [t for t in ages if t > 40]

# average of the 12 ages
a_ave = a_min + 11 * delta / 2
# lowest possible average age of a jury
min_ave = a_ave + (40 - max(ages)) / 12
# highest possible average age of a jury
max_ave = a_ave + (max(ages) - min(ages)) / 12
poss_aves = [p for p in primes
if p >= min_ave and p < max_ave]

# possible prime average ages for a jury,
# ...must be (at least) 2 of them
if len(poss_aves) < 2:
continue

# find twins' age by trial and error
for twin in twins:
rejects = []
for poss_ave in poss_aves:
# age of swapped juror relative to twins
swapped = twin + (a_ave - poss_ave) * 12
if swapped > a_min + 11 * delta:
break
# reject impossible juror ages
if swapped >= 20:
rejects.append(swapped)

# solution contains at least two swapped juror ages
if len(rejects) > 1:
# happily there is one solution
#.. and it has exactly two swapped jurors
print("The ages of the twins was", twin)

```

Like

• #### Tony Brooke-Taylor 12:04 pm on 26 June 2021 Permalink | Reply

Thanks all for your comments. I apologise for my continued struggles making my code readable in these replies. I’ll have a look at the Wingware IDE.

Like

• #### Hugh Casement 11:34 am on 27 June 2021 Permalink | Reply

With the same sequence the twins could have been aged 32, 35, or 38 (had those been allowed), still with the same two average ages. I found no other sequences that work, assuming no square ages .

Like

## Teaser 3057: Cut for partners

From The Sunday Times, 25th April 2021 [link]

George and Martha are playing bridge with an invited married couple. Before play starts, the players have to cut for partners. Each player draws a card from a standard pack and those drawing the two highest-ranking cards play together against the other two. For this purpose, the rank order is ♠ A, ♥ A, ♦ A, ♣ A, ♠ K, ♥ K etc. down to ♦ 3, ♣ 3, ♠ 2, ♥ 2, ♦ 2, ♣ 2 (the lowest).

George drew the first card, then Martha drew a lower-ranking card. “That is interesting!” commented the male visitor to his wife. “The probability that we shall play together is now P. Had Martha drawn the ♥ 7 instead of her actual card, that chance would have been reduced to P/2, and had she drawn the ♥ 6, the chance would have been reduced to P/3”.

Which cards did George and Martha draw?

[teaser3057]

• #### Jim Randell 5:30 pm on 23 April 2021 Permalink | Reply

The equations can be solved manually without too much trouble to give a direct solution, but here is a Python program that solves the puzzle. It runs in 45ms.

Run: [ @replit ]

```from enigma import P, irange, peek, printf

# the cards in order (highest to lowest)
cards = list(v + s for v in "AKQJX98765432" for s in "SHDC")

# index of certain cards we are interested in
(i6H, i7H) = (cards.index(c) for c in ('6H', '7H'))

# count number of pairs where X+Y play together
# given G chose card index g and M chose card index m
N = lambda g, m: P(g, 2) + P(51 - m, 2)

# choose a card for G
for g in irange(0, i7H - 2):

# count pairs if M had chosen 6H or 7H
ns = { 3 * N(g, i6H), 2 * N(g, i7H) }
if len(ns) > 1: continue

# choose a card for M
for m in irange(g + 1, i7H - 1):

# that gives the correct probability
if N(g, m) in ns:
# output solution
printf("G={G} [{g}]; n={n}; M={M} [{m}]", G=cards[g], M=cards[m], n=peek(ns))
```

Solution: George’s card is A♣. Martha’s card is 9♠.

Manually:

There are 52 cards to start with, and after George has chosen one (at index g in the list of cards) there are 51 remaining.

Martha chooses a lower card than George (at index m in the list of cards), and now there are 50 cards remaining.

The other couple (X and Y) then choose cards, and if they are both lower valued than Martha’s card, or higher valued than George’s card then they will play together.

The number of possible (unordered) pairs of cards for X+Y is: P(50, 2) = 2450, but that is the same in all scenarios, so we can just compare the number of pairs which result in X+Y playing together (n = 2450p).

The number of pairs which are better than George’s card is: P(g, 2)

And the number of pairs which are worse than Martha’s card is: P(51 − m, 2)

If Martha had chosen 6♥ (the card at index 33) the probability is p/3, so:

P(g, 2) + P(51 − 33, 2) = n / 3

If Martha had chosen 7♥ (the card at index 29) the probability is p/2, so:

P(g, 2) + P(51 − 29, 2) = n / 2

Together these solve to give:

P(22, 2) − P(18, 2) = n / 6
⇒ n = 936
g² − g − 6 = 0
(g + 2)(g − 3) = 0
⇒ g = 3

So G chose the card at index 3 = A♣.

(And the probability is p = 936/2450 ≈ 0.382).

To find Martha’s card:

P(g, 2) + P(51 − m, 2) = 936
m² − 101m + 2556 = 936
m² − 101m + 1620 = 0
(m − 20)(m − 81) = 0
⇒ m = 20

So M chose the card at index 20 = 9♠.

Like

• #### Frits 11:45 pm on 23 April 2021 Permalink | Reply

```from enigma import div

# chance is numerator / denominator
# P = lambda g, m: ((m - 1) * (m - 2)  + (52 - g) * (51 - g)) / (50 * 49)

# range cards: 1 - 52
# H7 is card 23, H6 = 19

suits = ["clubs", "diamonds", "hearts", "spades"]
nums = ["2", "3", "4", "5", "6", "7", "8", "9", "10",
"jack", "queen", "king", "ace"]

# check values for George
for g in range(25, 53):
G = (52 - g) * (51 - g)

h7_numerator = (23 - 1) * (23 - 2) + G
if h7_numerator % 3: continue

h6_numerator = 2 * h7_numerator // 3
if h6_numerator != (19 - 1) * (19 - 2) + G: continue

m_numerator = 2 * h7_numerator

# (m - 1) * (m - 2) + G = m_numerator, m^2 -3m + (2 + G - m_numerator) = 0
m = div(3 + (1 + 4 * (m_numerator - G)) ** 0.5, 2)
if m is None: continue
m = int(m)

print(f"George and Martha drew {nums[(g - 1) // 4]} of {suits[(g - 1) % 4]}"
f" and {nums[(m - 1) // 4]} of {suits[(m - 1) % 4]}")
```

With more analysis:

```from enigma import div

# range cards: 1 - 52

suits = ["clubs", "diamonds", "hearts", "spades"]
nums = ["2", "3", "4", "5", "6", "7", "8", "9", "10",
"jack", "queen", "king", "ace"]

# numerator of P = (m - 1) * (m - 2) + (52 - g) * (51 - g)
# P is twice the chance for H7 (card 23)

# (m - 1) * (m - 2) + (52 - g) * (51 - g) =
# 2 * ((23 - 1) * (23 - 2) + (52 - g) * (51 - g))

# g = 103 / 2 - ((4 * m^2 - 12*m - 3687) ^ 0.5) / 2

# P is three times the chance for H6 (card 19)

# (m - 1) * (m - 2) + (52 - g) * (51 - g) =
# 3 * ((19 - 1) * (19 - 2) + (52 - g) * (51 - g))

# g = 103 / 2 - ((2 * m^2 - 6*m - 1831) ^ 0.5) / 2

# (4 * m^2 - 12*m - 3687) - (2 * m^2 - 6*m - 1831) = 0
# 2 * m^2 - 6 * m - 1856 = 0
m = div(6 + (36 + 4 * 2 * 1856) ** 0.5, 4)
if m is None: exit()
m = int(m)

g = div(103 - (4 * m ** 2 - 12 * m - 3687) ** 0.5, 2)
if g is None: exit()
g = int(g)

print(f"George and Martha drew {nums[(g - 1) // 4]} of {suits[(g - 1) % 4]}"
f" and {nums[(m - 1) // 4]} of {suits[(m - 1) % 4]}")
```

Like

## Teaser 3053: Endless number

From The Sunday Times, 28th March 2021 [link]

George and Martha have a telephone number consisting of nine digits; there is no zero and the others appear once each. The total of the digits is obviously 45, so that the number is divisible by nine. Martha noticed that, if she removed the last (i.e., the least significant) digit, an eight-digit number would remain, divisible by eight. George added that you could continue this process, removing the least significant digit each time to be left with an n-digit number divisible by n right down to the end.

What is their telephone number?

[teaser3053]

• #### Jim Randell 5:04 pm on 26 March 2021 Permalink | Reply

See also: Enigma 339b, Enigma 1643, Enigma 1667, and the recently posed Puzzle #102.

Here’s a solution using the [[ `SubstitutedExpression` ]] solver from the enigma.py library. It runs in 96ms.

```#!/usr/bin/env python3 -m enigma -r

SubstitutedExpression

--digits="1-9"

"ABCDEFGH % 8 = 0"
"ABCDEFG % 7 = 0"
"ABCDEF % 6 = 0"
"ABCDE % 5 = 0"
"ABCD % 4 = 0"
"ABC % 3 = 0"
"AB % 2 = 0"

```

Solution: The number is 381654729.

Like

• #### Frits 10:40 pm on 26 March 2021 Permalink | Reply

Tested in a Python online editor.

```from itertools import permutations

print(*["".join(x) for x in permutations("123456789")
if all(int("".join(x[:i])) % i == 0 for i in range(2, 9))])
```

Like

• #### Tony Brooke-Taylor 9:02 pm on 28 March 2021 Permalink | Reply

I used a few shortcuts with the aim of minimising wasted iterations. Running my code on Replit takes about 3.5ms, compared with 1.13s for Frits’ sledgehammer approach. On the other hand, mine takes a few more lines!

Hope I manage to paste this in an appropriate format:

```
evens=list(range(2,9,2))
Xs=list(range(2,9,4))
odds=list(range(1,10,2))
odds.remove(5)

#Exploit the fact that the three-digit and six-digit numbers must be divisible by 3, and that the 6-digit number can be expressed as the sum of ABC*1000 and XYZ, so the digits of both ABC and XYZ must sum separately to 3. Let the last three digits be RST.

#For a four-digit number to be divisible by four, the last two digits must make a number divisible by four. Therefore if the third digit is odd, the fourth must be an odd multiple of 2
for X in Xs:
vec=[None for i in range(9)]
vec[4]=5#no zeros allowed, and the five-digit number divisible by 5
vec[3]=X
Z=10-X#consequence of sum(X,Y,Z) divisible by three
vec[5]=Z
Bs=[i for i in evens if i not in vec]#remaining evens go to 2nd and 8th
for B in Bs:
vec[1]=B
S=Bs[(Bs.index(B)-1)%2]
vec[7]=S

#Try each pair of odd numbers (other than 5) in positions 1 and 3, subject to requiring that ABC divisible by 3 (requiring A+B+C divisible by 3)
for A in odds:
Cs=odds.copy()
Cs.remove(A)
for C in Cs:
if sum([A,B,C])%3==0:
vec[0]=A
vec[2]=C

#Complementary odds then fall into positions 7 and 9
Rs=Cs.copy()
Rs.remove(C)
for R in Rs:
vec[6]=R
if sum([i*10**(6-vec.index(i)) for i in vec[:7]])%7==0 and sum([i*10**(7-vec.index(i)) for i in vec[:8]])%8==0:
Ts=Rs.copy()
Ts.remove(R)
for T in Ts:
vec[8]=T
print("The telephone number is",sum([i*10**(8-vec.index(i)) for i in vec[:9]]))

```

Like

• #### Frits 10:57 am on 29 March 2021 Permalink | Reply

Hi Tony,

A couple of recommendations:

index() is expensive so line 35 may be written to :

```
if sum([x * 10**(2 - i) for i, x in enumerate(vec[5:8])]) % 8 == 0 and \
sum([x * 10**(6 - i) for i, x in enumerate(vec[:7])]) % 7 == 0:
```

You can also use something like “dgts2nbr” as in puzzle [[ https://enigmaticcode.wordpress.com/2017/04/10/enigma-1120-assorted-numbers/ ]]

– line 16-19 can be rewritten to:

```
for j, B in enumerate(Bs):
vec[1] = B
vec[7] = Bs[1 - j]
```

or

```
for j in range(2):
vec[1] = Bs[j]
vec[7] = Bs[1 - j]
```

or

```
for (B, S) in permutations(Bs):
vec[1] = B
vec[7] = S
```

Like

• #### Tony 6:01 pm on 29 March 2021 Permalink | Reply

Thanks Frits: now I know about enumerate and reduce. As I’m getting the hang of looping over iterables I had forgotten it is still possible to loop with a counter, so I would probably choose your second approach to lines 16-19. I was trying to avoid using itertools once I realised I only needed to deal with pairs.

Like

• #### Hugh Casement 12:51 pm on 27 March 2021 Permalink | Reply

Isn’t this effectively the same as Brainteaser 1040 (4 July 1982)?

That one at least spared us George and Martha, who get dragged in again and again for no good reason.

Like

• #### Jim Randell 3:36 pm on 27 March 2021 Permalink | Reply

@Hugh: It does seem to be. I suppose it is hard to come up with over 3000 puzzles without some overlap. Or to check that there is no overlap!

Like

• #### Hugh Casement 1:14 pm on 30 March 2021 Permalink | Reply

And the recent Puzzle 102 in New Scientist. I call that plagiarism!

Like

• #### GeoffR 1:39 pm on 20 May 2021 Permalink | Reply

```from itertools import permutations
from enigma import join

# the number 45 is divisible by nine
i = 9

for p in permutations('123456789', 8):
a, b, c, d, e, f, g, h = p

# A geometric pattern to this code

if int(a + b + c + d + e + f + g + h) % 8 == 0:
if int(a + b + c + d + e + f + g) % 7 == 0:
if int(a + b + c + d + e + f) % 6 == 0:
if int(a + b + c + d + e) % 5 == 0:
if int(a + b + c + d) % 4 == 0:
if int(a + b + c) % 3 == 0:
if int(a + b) % 2 == 0:
tel_num = join((a, b, \
c, d, e, f, g, h, i))
print('No. is',tel_num)
# No. is 381654729

```

Like

• #### Dirk 9:43 am on 9 July 2021 Permalink | Reply

Teaser 1882 (11/10/1998): Multiple Solutions by Rex Gooch is also linked with brainteaser 1040/3053.

Like

## Teaser 3046: Square phone numbers

From The Sunday Times, 7th February 2021 [link]

George and Martha run a business in which there are 22 departments. Each department has a perfect-square three-digit extension number, i.e., everything from 100 (10²) to 961 (31²), and all five of their daughters are employees in separate departments.

Andrea, Bertha, Caroline, Dorothy and Elizabeth have extensions in numerical order, with Andrea having the lowest number and Elizabeth the highest. George commented that, if you look at those of Andrea, Bertha and Dorothy, all nine positive digits appear once. Martha added that the total of the five extensions was also a perfect square.

What is Caroline’s extension?

[teaser3046]

• #### Jim Randell 5:03 pm on 5 February 2021 Permalink | Reply

A simple Python program finds the solution in 67ms.

Run: [ @repl.it ]

```from enigma import powers, subsets, concat, is_square, printf

# possible square numbers
squares = powers(10, 31, 2)

# choose 5 of the squares (in order)
for (A, B, C, D, E) in subsets(squares, size=5):

# the sum of the numbers is also a square
if not is_square(A + B + C + D + E): continue

# A, B, D use the digits 1-9
ds = concat(A, B, D)
if '0' in ds or len(set(ds)) != 9: continue

# output solution
printf("A={A} B={B} C={C} D={D} E={E}")
```

Solution: Caroline’s extension is 729.

Manually, you can write out the squares, and then working through the possible candidates for A, B, D, the solution is discovered quite quickly.

Like

• #### GeoffR 7:51 pm on 5 February 2021 Permalink | Reply

```
% A Solution in MiniZinc
include "globals.mzn";

% Andrea, Bertha, Caroline, Dorothy and Elizabeth's numbers
var 100..961:A; var 100..961:B; var 100..961:C;
var 100..961:D; var 100..961:E;

constraint all_different([A, B, C, D, E]);
constraint A < B /\ B < C /\ C < D /\ D < E;

% digits for squares A, B and D
var 1..9:a1; var 1..9:a2; var 1..9:a3;
var 1..9:b1; var 1..9:b2; var 1..9:b3;
var 1..9:d1; var 1..9:d2; var 1..9:d3;

% all 3-digit squares
set of int: sq3 = {n*n | n in 10..31};

predicate is_sq(var int: y) =
exists(z in 1..ceil(sqrt(int2float(ub(y)))))
(z*z = y);

% the total of the five extensions was also a perfect square
constraint is_sq(A + B + C + D + E);

% all five telephone extensions are 3-digit squares
constraint A in sq3 /\ B in sq3 /\ C in sq3 /\ D in sq3 /\ E in sq3;

% digit components in squares A, B and D
constraint a1 == A div 100 /\ a2 == A div 10 mod 10 /\ a3 == A mod 10;
constraint b1 == B div 100 /\ b2 == B div 10 mod 10 /\ b3 == B mod 10;
constraint d1 == D div 100 /\ d2 == D div 10 mod 10 /\ d3 == D mod 10;

set of int: all_dig ={1, 2, 3 ,4, 5, 6, 7, 8, 9};
var set of int: S1 == {a1, a2, a3, b1, b2, b3, d1, d2, d3};
constraint all_dig == S1;

solve satisfy;

output ["Caroline's extension is " ++ show(C)
++"\nOther extensions are " ++ show(A) ++ ", " ++ show(B)
++ ", " ++ show(D) ++ ", " ++ show(E) ];

```

Like

• #### GeoffR 8:44 am on 6 February 2021 Permalink | Reply

```from itertools import combinations
from enigma import nsplit, is_square

squares =[x * x for x in range(10, 32)]

for A, B, C, D, E in combinations(squares, 5):
# five extensions are in numerical order
if A < B < C < D < E:
sq_total = A + B + C + D + E
if is_square(sq_total):
# find individual digits of A, B and D
a1, a2, a3 = nsplit(A)
b1, b2, b3 = nsplit(B)
d1, d2, d3 = nsplit(D)
S1 = set((a1, a2, a3, b1, b2, b3, d1, d2, d3))
# check this set contains nine positive digits
if len(S1) == 9 and 0 not in S1:
print(f"Five extensions are {A}, {B}, {C}, {D}, {E}")

```

Like

• #### Frits 7:44 pm on 6 February 2021 Permalink | Reply

```squares = [x * x for x in range(15, 66)]
ABD_squares = [x * x for x in range(13, 31)
if len(set(str(x * x) + "0")) == 4]

for i, a in enumerate(ABD_squares[:-2]):
for j, b in enumerate(ABD_squares[i + 1:-1]):
if len(set(str(a) + str(b))) != 6: continue
for d in ABD_squares[i + j + 2:]:
if len(set(str(a) + str(b) + str(d))) != 9: continue
p = squares.index(b)
q = squares.index(d)

for c in squares[p + 1:q]:
for e in squares[q + 1:17]:
if not (a + b + c + d + e) in squares: continue
print(f"Caroline's extension is {c}.")
```

Like

• #### Tony Brooke-Taylor 10:21 am on 7 February 2021 Permalink | Reply

```import itertools

digits = set([str(j) for j in range(1, 10)])

for M in itertools.combinations([i**2 for i in range(10, 32)], 5):
if (sum(M)**(1/2))%1 == 0:
if set(str(M[0])+str(M[1])+str(M[3])) == digits: print("Caroline's extension is", M[2])
```

Like

• #### Frits 4:21 pm on 7 February 2021 Permalink | Reply

Logic can reduce a,b and d to specific squares.
The version without reduction logic is faster.

```from collections import defaultdict

squares = [x * x for x in range(15, 66)]
ABD_squares = [x * x for x in range(13, 31)
if len(set(str(x * x) + "0")) == 4]

# return first column
col0 = lambda li: [x[0] for x in li]

fixed = set()
str_fixed = ""
mut_excl = defaultdict(set)

# reduce candidates in list <ABD_squares>
# by looking for digits occurring once or twice in list <ABD_squares>
for loop in range(9):
occ = defaultdict(list)

for x in "123456789":
# add entries to occurence dictionary <occ>
for i, s in enumerate(ABD_squares):
s1 = str(s)
if x not in s1 or s1 in fixed: continue
# skip if a square digit already occurs in <fixed>
if any(y in str_fixed for y in s1): continue
occ[x].append([i, s1])

if len(occ[x]) == 1:
# a square has to occur in <ABD_squares>
if not occ[x][0][1] in fixed:
str_fixed = "".join(fixed)
# also update occurrence for other 2 related digits to same square
for c in occ[x][0][1]:
if c == x: continue
occ[c] = occ[x]
elif len(occ[x]) == 2:
# we have a square with digits x,e,f and a square with digits x,g,h
# so e, e, f, f may not occur in another square with resp. g, h ,g, h
for y in occ[x][0][1]:
if y == x: continue
for z in occ[x][1][1]:
if z == x: continue

# check if 2 digits always occur in different squares
for x1, y1 in occ.items():
for x2, y2 in occ.items():
if x1 >= x2: continue
if len(set(col0(y1) + col0(y2))) != \
len(col0(y1)) + len(col0(y2)): continue
# digit x1 and x2 occur in different squares
# so maintain dictionary <mut_excl>

# reduce squares if a square contains mutually exclusive digits
ABD_squares = [s for s in ABD_squares
if not any(m in str(s) for y in str(s)
for m in mut_excl[y])
]

if len(ABD_squares) == 3: break

for i, a in enumerate(ABD_squares[:-2]):
for j, b in enumerate(ABD_squares[i + 1:-1]):
if len(set(str(a) + str(b))) != 6: continue
for d in ABD_squares[i + j + 2:]:
if len(set(str(a) + str(b) + str(d))) != 9: continue
p = squares.index(b)
q = squares.index(d)

for c in squares[p + 1:q]:
for e in squares[q + 1:17]:
if not (a + b + c + d + e) in squares: continue
print(f"Caroline's extension is {c}.")
```

Like

• #### Frits 1:25 pm on 8 February 2021 Permalink | Reply

Not very efficient.

```# decompose a number into <k> increasing 3-digit squares a, b, c, d, e
# (a, b, d) has to contain all digits 1-9
def decompose(t, k, m=1, ss=[]):
if k == 1:
# check if last number is higher and a square
if t > ss[-1] and int(t ** 0.5) ** 2 == t:
yield ss + [t]
else:
for i in range(m, 32 - k + 1):
s = i * i
if s > t: break

if k in {3, 1} or len(set(str(s) + "0")) == 4:
yield from decompose(t - s, k - 1, i + 1, ss + [s])

# sum first five 3-digit squares is 750 and last five 3-digit squares is 4215
for r in range(28, 65):
# get five 3-digit squares which add up to square <r * r>
for x in decompose(r * r, 5, 10):
sabd = set(str(1000000 * x[0] + 1000 * x[1] + x[3]))
if len(sabd) != 9: continue

print(f"Caroline's extension is {x[2]}.")
```

Like

## Teaser 3038: Progressive raffle

From The Sunday Times, 13th December 2020 [link]

George and Martha were participating in the local village raffle. 1000 tickets were sold, numbered normally from 1 to 1000, and they bought five each. George noticed that the lowest-numbered of his tickets was a single digit, then each subsequent number was the same multiple of the previous number, e.g. (7, 21, 63, 189, 567). Martha’s lowest number was also a single digit, but her numbers proceeded with a constant difference, e.g. (6, 23, 40, 57, 74). Each added together all their numbers and found the same sum. Furthermore, the total of all the digits in their ten numbers was a perfect square.

What was the highest numbered of the ten tickets?

[teaser3038]

• #### Jim Randell 4:52 pm on 11 December 2020 Permalink | Reply

If the sum of the 5 terms of the geometric progression is t, and this is also the sum of the 5 term arithmetic progression (a, a + d, a + 2d, a + 3d, a + 4d), then we have:

t = 5(a + 2d)

So the sum must be a multiple of 5.

The following Python program runs in 44ms.

Run: [ @repl.it ]

```from enigma import irange, div, union, nsplit, is_square, printf

# generate geometric progressions with k elements
# n = max value for 1st element, N = max value for all elements
def geom(k, n=9, N=1000):
# first element
for a in irange(1, n):
# second element is larger
for b in irange(a + 1, N):
# calculate remaining elements
(gs, rs, x) = ([a, b], 0, b)
while len(gs) < k:
(x, r) = divmod(x * b, a)
gs.append(x)
rs += r
if x > N: break
if rs == 0:
yield tuple(gs)

# digit sum of a sequence
dsums = lambda ns: sum(nsplit(n, fn=sum) for n in ns)

# consider geometric progressions for G
for gs in geom(5):
x = div(sum(gs), 5)
if x is None: continue

# arithmetic progressions for M, with the same sum
# and starting with a single digit
for a in irange(1, 9):
d = div(x - a, 2)
if d is None: continue
ms = tuple(irange(a, a + 4 * d, step=d))
ns = union([gs, ms])
if len(ns) != 10: continue

# the sum of the digits in all the numbers is a perfect square
r = is_square(dsums(ns))
if r is None: continue

m = max(gs[-1], ms[-1])
printf("max = {m}; gs = {gs}, ms = {ms}; sum = {t}, dsum = {r}^2", t=5 * x)
```

Solution: The highest numbered ticket is 80.

Note that the [[ `geom()` ]] function will generate all possible geometric progressions, including those that have a non-integer common ratio, (e.g. for a 4 element progression we could have (8, 28, 48, 343)), but for a 5 element progression we would need the initial term to have a factor that is some (non-unity) integer raised to the 4th power, and the smallest possible value that would allow this is 2^4 = 16, which is not possible if the initial term is a single digit. So for this puzzle the solution can be found by considering only those progressions with an integer common ratio (which is probably what the puzzle wanted, but it could have said “integer multiple” to be completely unambiguous).

Like

• #### GeoffR 7:48 pm on 11 December 2020 Permalink | Reply

```% A Solution in MiniZinc
include "globals.mzn";

% terms of arithmetic series
var 1..9: A1; var 2..100: A2;var 2..150: A3;
var 2..250: A4; var 2..500: A5;

% terms of geometric series
var 1..9: G1; var 2..100: G2;var 2..150: G3;
var 2..250: G4; var 2..500: G5;

% geometric ratio and arithmetic difference
var 2..9:Gratio;

%  total sum of  geometric and arithmetic series
var 2..500: Gsum;
var 2..500: Asum;

% maximum raffle ticket number
var 2..999: max_num;

constraint A2 == A1 + Adiff;
constraint A3 == A2 + Adiff;
constraint A4 == A3 + Adiff;
constraint A5 == A4 + Adiff;

constraint Asum = A1 + A2 + A3 + A4 + A5;

constraint G2 == G1*Gratio;
constraint G3 == G2*Gratio;
constraint G4 == G3*Gratio;
constraint G5 == G4*Gratio;

constraint Gsum = G1 + G2 + G3 + G4 + G5;

constraint Gsum == Asum;

constraint all_different ([A1,A2,A3,A4,A5,G1,G2,G3,G4,G5]);

constraint max_num = max({A1,A2,A3,A4,A5,G1,G2,G3,G4,G5});

solve satisfy;

output[ "Geometric Series: " ++ show([G1,G2,G3,G4,G5])
++ "\n" ++ "Arithmetic Series = " ++ show([A1,A2,A3,A4,A5])
++ "\n" ++ "Max ticket number = " ++ show(max_num) ];
```

This programme produces three solutions, all with the same maximum value.
In only one of the solutions do the digits add to a perfect square.

Like

• #### Jim Randell 8:05 pm on 11 December 2020 Permalink | Reply

@Geoff: There’s only one copy of each ticket, so both George and Martha’s sets of numbers are fully determined. (Even though we are only asked for the highest numbered ticket).

Like

• #### Frits 2:30 pm on 12 December 2020 Permalink | Reply

```for k in range(2, 6):
print(sum(k**i for i in range(5)))
```

The result of this piece of code are all numbers ending on a 1. This limits George’s lowest-numbered ticket to one number.

Like

• #### Frits 7:57 pm on 12 December 2020 Permalink | Reply

The generated code can be seen with option verbose=256.

```from enigma import SubstitutedExpression, is_prime, is_square, \
seq_all_different

# Formula
# G * (1 + K + K^2 + K^3 + K^4) == 5 * (M + 2*D)

# (1 + K + K^2 + K^3 + K^4) equals (K^5 - 1) / (K - 1)

# sum the digits of the numbers in a sequence
dsums = lambda seq: sum(sum(int(x) for x in str(s)) for s in seq)

# domain lists
dlist = list(range(3))  # d < 250
elist = list(range(10))
flist = list(range(10))
glist = list(range(1, 10))
klist = []
mlist = list(range(1, 10))

lastdigit = set()           # last digit of the total of 5 tickets
# K^4 may not be higher than 1000, so K < 6
for k in range(2, 6):
t = sum(k**i for i in range(5))
klist.append(k)

lastdigit = list(lastdigit)

if 5 not in lastdigit:
# George's lowest ticket must be 5 as total is a multiple of 5
glist = [5]

if len(lastdigit) == 1:
# Martha's tickets sum to 5 * (M + 2*D)
if lastdigit[0] % 2 == 1:
# Martha's lowest ticket must be odd
mlist = [1, 3, 5, 7, 9]
else:
# Martha's lowest ticket must be even
mlist =[2, 4, 6, 8]

if len(glist) == 1:
# George's highest ticket may not be higher than 1000
klist = [x for i, x in enumerate(klist, start=2)
if i**4 * glist[0] <= 1000]
# calculate highest sum of 5 tickets
t = sum(max(klist)**i for i in range(5)) * glist[0]

# Martha's highest ticket may not be higher than (t/5 - M) / 2
dlist = [x for x in dlist if x <= (t / 10) // 100]
if dlist == [0]:
elist = [x for x in elist if x <= (t // 10) // 10]

mlist = [x for x in mlist if x != glist[0]]

# build dictionary for invalid digits
vars = "DEFGKM"
invalid = "dict("
for i in range(10):
txt = ""
for j, li in enumerate([dlist, elist, flist, glist, klist, mlist]):
if i not in li:
txt += vars[j]
invalid += "[(" + str(i) + ", '" + txt + "')] + "

invalid = invalid[:-3] + ")"

exprs = []

# George's and Martha's sum was the same
exprs.append("G * (K ** 5 - 1) // (K - 1) == 5 * (M + 2 * DEF)")
# all ticket numbers have to be different
exprs.append("seq_all_different([G, G * K, G * K**2, G * K**3, G * K**4, \
M, M + DEF, M + 2*DEF, M + 3*DEF, M + 4*DEF])")
# total of all the digits in the ten numbers was a perfect square
exprs.append("is_square(dsums([G, G * K, G * K**2, G * K**3, G * K**4, \
M, M + DEF, M + 2*DEF, M + 3*DEF, M + 4*DEF]))")

# the alphametic puzzle
p = SubstitutedExpression(
exprs,
answer="(G, G * K, G * K**2, G * K**3, G * K**4), \
(M, M + DEF, M + 2*DEF, M + 3*DEF, M + 4*DEF), 5 * (M + 2 * DEF)",
d2i=eval(invalid),
env=dict(dsums=dsums),
distinct="GM",
verbose=0)

for (_, ans) in p.solve():
print(f"{ans}")
```

Like

• #### Tony Brooke-Taylor 9:10 am on 14 December 2020 Permalink | Reply

My first solution generated the series explicitly and then applied the tests to each series, but then I realised we could equate the expressions for the sums of each series to reduce the sets of parameters we need to test. My second attempt was similar to below but instead of constraining the sum to a multiple of 5 I initially constrained my ‘b’ parameter to an integer, which I think is mathematically equivalent but came inside another loop so was less efficient.

```#Generator function to create possible combinations of parameters for George and Martha
def core_parameters():
#George's tickets form the geometric progression x.(y^0, y^1, y^2, y^3, y^4)
#Martha's tickets form the arithmetic progression (a+b*0, a+b*1, a+b*2, a+b*3, a+b*4)

for x in range(1,10): #we are told that George's first ticket has a single-digit value
max_y = int((1000/x)**(0.25)//1)+1 #defined by the maximum possible value for George's highest-value ticket
for y in range(2,max_y): #y=1 not possible because this would give all George's tickets the same value

sum_values = x*(1-y**5)/(1-y) #sum of finite geometric progression
#sum_values = a*5 + b*10      #sum of finite arithmetic progression
#=> b = (sum_values - a*5)/10 = sum_values/10 - a/2
if sum_values%5 == 0:      #equality also requires that the sum is a multiple of 5

for a in range(1,10): #we are told that Martha's first ticket has a single-digit value
if a != x:          #Martha's first ticket cannot have the same value as George's
b = sum_values/10 - a/2
yield x, y, a, b

#Function to sum all digits in an integer
def digit_sum(num):
s = 0
for dig in str(num):
s = s + int(dig)
return s

#Control program

for first_george_ticket, george_multiple, first_martha_ticket, martha_multiple in core_parameters():
george_tix = [first_george_ticket*george_multiple**n for n in range(5)]
martha_tix = [int(first_martha_ticket+martha_multiple*m) for m in range(5)]

#they can't both have the same ticket and we are told that the sum of all digits is a square
if set(martha_tix).intersection(george_tix) == set() and \
((sum([digit_sum(j) for j in george_tix]) + sum([digit_sum(k) for k in martha_tix]))**(1/2))%1 == 0:

print("George:", george_tix)
print("Martha:", martha_tix)
print("Highest-valued ticket:",max(george_tix + martha_tix))
break
```

Like

## Teaser 2769: Coming home

George, Martha and their daughter all drive at their own steady speeds (whole numbers of mph), the daughter’s speed being 10mph more than Martha’s. One day George left home to drive to his daughter’s house at the same time as she left her house to visit her parents: they passed each other at the Crossed Keys pub. Another time Martha left her daughter’s to return home at the same time as her daughter started the reverse journey: they too passed at the Crossed Keys. The distance from George’s to the pub is a two-figure number of miles, and the two digits in reverse order give the distance of the pub from their daughter’s.

How far is it from George’s home to the Crossed Keys?

[teaser2769]

• #### Jim Randell 9:17 am on 1 December 2020 Permalink | Reply

This Python program considers candidate 2-digit distances from the parent’s house to the pub. It runs in 43ms.

Run: [ @repl.it ]

```from enigma import irange, nreverse, div, printf

# consider 2 digit distance from parent's house to X
for p in irange(10, 99):
# distance to the daughter's house to X is the reverse
d = nreverse(p)
if not(d < p): continue

# in the second journey the mother's speed is...
vm = div(10 * d, p - d)
if vm is None: continue
vd = vm + 10

# in the first journey the father's speed is...
vf = div(p * vd, d)
if vf is None: continue

printf("p={p} d={d}, vm={vm} vd={vd} vf={vf}")
```

Solution: It is 54 miles from George’s house to the Crossed Keys.

So it is 45 miles from the daughter’s house.

The speeds are: mother = 50 mph, daughter = 60 mph, father = 72 mph.

Like

## Teaser 2761: Digital shuffle

George and Martha have nine cards with a different non-zero digit on each. To teach their nephew to count they lined up the cards in increasing order. He then rearranged the order of the line and Martha was impressed when she noticed that no digit was in its original position. George was even more impressed when he found that the six-figure number formed by the last six cards was the square of the three-figure number formed by the first three.

What was that three-figure number?

[teaser2761]

• #### Jim Randell 2:59 pm on 27 October 2020 Permalink | Reply

We can use the [[ `SubstitutedExpression` ]] solver from the enigma.py library to solve this alphametic puzzle.

The following run file executes in 99ms.

Run: [ @repl.it ]

```#!/usr/bin/env python -m enigma -r

SubstitutedExpression

# non-zero digits
--digits="1-9"

# no digit is in its original position
--invalid="1,A"
--invalid="2,B"
--invalid="3,C"
--invalid="4,D"
--invalid="5,E"
--invalid="6,F"
--invalid="7,G"
--invalid="8,H"
--invalid="9,I"

"ABC ** 2 = DEFGHI"

```

Solution: The three-figure number was 854.

Giving:

854² = 729316

If we remove the condition that “no digit is in its original position”, we find there is a further solution to the alphametic of:

567² = 321489

But this is disallowed as the digits 8 and 9 are in positions 8 and 9.

Like

• #### GeoffR 4:23 pm on 27 October 2020 Permalink | Reply

```% A Solution in MiniZinc
include "globals.mzn";

var 1..9:A; var 1..9:B; var 1..9:C; var 1..9:D;
var 1..9:E; var 1..9:F; var 1..9:G; var 1..9:H;
var 1..9:I;

constraint all_different ([A,B,C,D,E,F,G,H,I]);

% Nine cards not in original position
constraint A != 1 /\ B != 2 /\ C != 3
/\ D != 4 /\ E != 5 /\ F != 6
/\ G != 7 /\ H != 8 /\ I != 9;

% Number formed by 1st three cards
var 100..999: ABC = 100*A + 10*B + C;

% Number formed by last six cards
var 100000..999999: DEFGHI = 100000*D + 10000*E
+ 1000*F + 100*G + 10*H + I;

%  the six-figure number formed by the last six cards was
% the square of the three-figure number formed by the first three
constraint DEFGHI = ABC * ABC;

solve satisfy;

output ["Three figure number was " ++ show(ABC)
++"\nSix figure number was " ++ show(DEFGHI) ];

% Three figure number was 854
% Six figure number was 729316
% ----------
% ==========

```

Like

• #### Frits 10:47 am on 28 October 2020 Permalink | Reply

```from itertools import dropwhile, count

# return True if not all rules are met
def wrongSquare(trueList):

# check if number meets the rules
def OK(x):
# booleans
bs = trueList.copy()

i = 0
while x and i < 9:
y = x % 10
# no derangement
if y != 9 - i:
bs[y] = False
x //= 10
i += 1
# all digits 1-9 used and no zero
return sum(bs) == 1 and bs[0]

return lambda n: not OK(1000000 * n + (n * n))

trueList = [True] * 10
sol = next(dropwhile(wrongSquare(trueList), count(317)))
print(f"{sol}^2 = {sol*sol}")
```

Like

• #### GeoffR 1:43 pm on 28 October 2020 Permalink | Reply

```
from itertools import permutations

for p1 in permutations('123456789'):
a, b, c, d, e, f, g, h, i = p1
# check numbers not in increasing order
# no digit is in its original position
if (a == '1' or b == '2' or c == '3' or
d == '4' or e == '5' or f == '6' or
g == '7' or g == '8' or i == '9'):
continue
# form 3-digit and 6-digit numbers
abc = int(a + b + c)
defghi = int(d + e + f + g + h + i)
if abc ** 2 == defghi:
print(f"Three digit number is {abc}")
print(f"Six digit number is {defghi}")

# Three digit number is 854
# Six digit number is 729316

```

Like

## Teaser 3023: Timely coincidence

From The Sunday Times, 30th August 2020 [link]

George and Martha possess two digital “clocks”, each having six digits. One displays the time on a 24-hour basis in the format hh mm ss, typically 15 18 45, and the other displays the date in the format dd mm yy, typically 18 07 14.

On one occasion, George walked into the room to find that the two “clocks” displayed identical readings. Martha commented that the long-term (400-year) average chance of that happening was 1 in just over a six-digit number. That six-digit number gives the birth date of one their daughters.

On what date was that daughter born?

[teaser3023]

• #### Jim Randell 7:35 pm on 28 August 2020 Permalink | Reply

On any particular day (ignoring jumps in time, such as leap seconds, daylight savings time, calendar reforms, etc.) there is either a 1/86400 chance of observing the clocks displaying the same an any given second (assuming they clocks are equally likely to be observed at any particular second of the day – which is unlikely), or a 0/86400 chance if the date does not correspond to a valid time.

The following Python program runs in 100ms.

Run: [ @repl.it ]

```import datetime
from enigma import int2base, printf

# consider a 400 year period, and count dates that give a valid time
d = datetime.date(day=1, month=1, year=1900)
i = datetime.timedelta(days=1)
n = 0
t = 0
while d.year < 2300:
if d.day < 24 and d.year % 100 < 60: n += 1
d += i
t += 1

# output solution
t *= 86400
x = t // n
printf("p = {n} / {t} (~ 1 / {x}); date = {b}", b=int2base(x, group=2, sep=".", width=6))
```

Solution: The daughter was born on 19th May 1961.

In order for the date to be read as a valid time we need the day of the month to be in the range 1-23, and the last 2 digits of the year to be in the range 0-59.

In each year of the required range there are 23×12 = 276 viable days.

In each 100 year period there are 60×276 = 16560 viable days.

In each 400 year period there are 4×16560 = 66240 viable days.

And in a 400 year period there is a total of 400×365 + 100 − 3 = 400×365.2425 = 146097 days.

Converting to seconds we get a chance of 1 in (146097 × 86400 / 66240) = 190561.304….

Truncating this result to an integer and reading as a date gives: Friday, 19th May 1961.

Like

## Teaser 2677: One for each day

From The Sunday Times, 12th January 2014 [link]

George and Martha have been looking into tests for divisibility,  including one for the elusive number seven. George wrote down a thousand-figure number by simply writing one particular non-zero digit a thousand times. Then he replaced the first and last digits by another non-zero digit to give him a thousand-figure number using just two different digits. Martha commented that the resulting number was divisible by seven. George added that it was actually divisible by exactly seven of 2, 3, 4, 5, 6, 7, 8, 9 and 11.

What were the first two digits of this number?

Note: This puzzle is marked as flawed, as under the intended interpretation there is no solution.

[teaser2677]

• #### Jim Randell 9:06 am on 25 August 2020 Permalink | Reply

Although the puzzle is flawed, I didn’t have a problem solving it, as I interpreted the “actually” in George’s statement to mean that George was correcting Martha’s statement, so it didn’t really matter if Martha’s statement was true or false. All we needed to do was find a number divisible by exactly seven of the given divisors. Which is what my code does, and it finds a unique solution, so I was happy enough with the puzzle.

Python’s support for large integers means this one can be solved in a straightforward way. The following program runs in 55ms.

Run: [ @replit ]

```from enigma import (subsets, printf)

digits = "123456789"
divisors = (2, 3, 4, 5, 6, 7, 8, 9, 11)

for (a, b) in subsets(digits, size=2, select="P"):
n = int(a + b * 998 + a)
ds = list(d for d in divisors if n % d == 0)
if len(ds) == 7:
printf("a={a} b={b} [ds={ds}]")
```

Solution: The first two digits of George’s number are 6 and 3.

So the 1,000-digit number is 6333…3336. Which is divisible by 2, 3, 4, 6, 8, 9, 11.

However, apparently the setter intended Martha’s statement to be true, and the number to be divisible by 7 and exactly six of the other divisors. Unfortunately, there is no such number. (As we can see by adding [[ `and 7 in ds` ]] to the condition on line 9).

The intended solution was 2777…77772, and the setter mistakenly determined that this was divisible by 8. In fact the number is divisible by only six of the divisors: 2, 3, 4, 6, 7, 11.

Like

• #### Hugh+Casement 11:33 am on 26 December 2021 Permalink | Reply

The puzzle could have stated that the number is an integer multiple of seven of the integers 2 to 12 inclusive.

However, we don’t need the ability to handle huge numbers (or even a computer).

We can regard the number as jk followed by 498 blocks of kk followed by kj.
The test for divisibility by 11 involves taking the alternating positive and negative sum of the digits. jk and kj cancel out, and each kk cancels, so the alternating digit sum is 0: the number is an integer multiple of 11 whatever the values of j and k.

It cannot be a multiple of 10 since we were told the digits are non-zero.

A test for divisibility by 7 is to take the alternating positive and negative sum of groups of three digits from the right. If and only if the result is a multiple of 7 is the overall number also a multiple of 7.

In this case we have a number with j on the left, then 332 blocks of kkk, and kkj on the right.
The even number of blocks cancel out, leaving kkj − j = kk0 = k × 110.
That is an integer multiple of 7 only if k = 7.

If the number is not a multiple of 2 then it cannot be a multiple of 4, 6, 8, or 12.
If it is not a multiple of 3 then it cannot be a multiple of 6, 9, or 12.
In order to have seven factors in the list it must be a multiple of both 2 and 3.

If j = 2 the number is an integer multiple of 2 and 4 (but, as Jim says, not 8).

So now we know j and k.
We can regard the number as 27 followed by 332 blocks of 777 followed by 72.
777 is a multiple of 3, so the digit sum is a multiple of 3 and the number is an integer multiple of 3 (but not of 9). Being a multiple of 3 and 4 it is also a multiple of 12.

The number is not a multiple of 5, 8, or 9 (nor 10).

Like

c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r