From The Sunday Times, 9th July 1989 [link]
Five families, each consisting of a mother, father, and one child, are near neighbours. The families have a lot in common, and, to give you some idea of the closeness, I will tell you that last Saturday all 15 family members went on an outing to the circus to celebrate young Laura’s 10th birthday.
The day before that, four of the mothers, Jenny, Lorna, Margaret and Norma, had been on a shopping spree together, and two of the fathers, Ken and John, had prepared a barbecue for all the others. Three of the children, Kevin, Marion and Nigel, are learning the piano under the same teacher.
Mike and Neil are the fathers of daughters. Young Jill, who is not Neil’s child, shares a birthday with Leo’s child (who has the same initial as Mike’s wife) and with Kate’s child (who has the same initial as Leo’s wife). The other two children share a birthday on a different date.
If I tell you that no two members of a family have the same first name initials as each other, you should be able to work out the name of John’s wife and who it was that shared Laura’s birthday last week.
There are now 1400 Teaser puzzles available on the site, so it seemed like an appropriate time to post Teaser 1400.
Between S2T2 and Enigmatic Code there are now 4056 puzzles available in total.
[teaser1400]
Jim Randell 7:48 am on 1 November 2026 Permalink |
I wasn’t sure if we were to discard rearrangements that had a leading zero. Although in the end it doesn’t matter if we do or not. [I decided that the most likely reading is that the puzzle wants us to consider all 3-digit rearrangements of the original number, so we need to allow for leading zeros in the tests].
This Python program is a straightforward search of all multiples of 3 in the range [100, 400] with the property, and then checks if (n − 1) also has the property.
It runs in 70ms. (Internal runtime is 3.7ms).
from enigma import (irange, subsets, nsplit, nconcat, primes, seq_ordered, cache, printf) # primes up to 3 digits primes.expand(999) # numbers that are the sum of two primes sum_of_primes = set() for p in primes.between(2, 500): sum_of_primes.update(p + q for q in primes.between(p, 999 - p)) # numbers that are the difference of two squares diff_of_squares = set() for a in irange(0, 500): sq_a = a * a for b in irange(a, 0, step=-1): d = sq_a - b * b if d > 999: break diff_of_squares.add(d) @cache def check_digits(ds): # all rearrangements of the digits <ds> ns = list(subsets(ds, size=len, select='mP', fn=nconcat)) # total number of rearrangements t = len(ns) return ( # <t> of them are sum of two primes len(sum_of_primes.intersection(ns)) == t and # (2/3) <t> of them are diff of two squares 3 * len(diff_of_squares.intersection(ns)) == 2 * t ) # check number <n> def check(n): # numbers using the same digits will give the same result return check_digits(nsplit(n, fn=seq_ordered)) # consider possible multiples of 3 for n in irange.round(100, 400, step=3, rnd='I'): if check(n) and check(n - 1): printf("lockers = {n} and {n1}", n1=n - 1)Solution: [To Be Revealed]
LikeLike
Jim Randell 3:31 pm on 1 November 2026 Permalink |
Here’s an alternative approach, which looks at possible sets of 3 digits, to find which sets have arrangements which satisfy the requirements (which have been reduced analytically to simple tests), and then adds those that are viable locker numbers to a set of candidates.
We then look for 2 locker numbers in the candidate set, where one is a multiple of 3, and the other is the preceding integer.
It has an internal runtime of 3.5ms, so is slightly faster.
from enigma import (irange, subsets, nconcat, primes, printf) # primes up to 3-digits primes.expand(999) def is_sum_of_two_primes(n): # even numbers: Goldbach's conjecture has been verified for n up to 4e+18 # odd numbers: n = 2 + p return (n > 2 if n % 2 == 0 else primes.contains(n - 2)) def is_diff_of_two_squares(n): # only numbers with n % 4 != 2 can be expressed as the difference of two squares return (n % 4 != 2) # record locker numbers with the required properties ns = set() # consider 3-digits for ds in subsets(irange(0, 9), size=3, select='R'): # arrange the digits into numbers rs = list(subsets(ds, size=len, select="mP", fn=nconcat)) # total count t = len(rs) # how many are the difference of two squares d = sum(1 for n in rs if is_diff_of_two_squares(n)) if 3 * d != 2 * t: continue # how many are the sum of two primes? p = sum(1 for n in rs if is_sum_of_two_primes(n)) if p != t: continue # record numbers in the designated range for n in rs: if 100 <= n <= 400: ns.add(n) # look for consecutive pairs for n in ns: if n % 3 == 0 and n - 1 in ns: printf("lockers = {n} and {n1}", n1=n - 1)LikeLike
Ruud van der Ham 9:17 am on 1 November 2026 Permalink |
import istr def is_sum_of_two_primes(n): return any(i.is_prime() and (n - i).is_prime() for i in istr.range(2, n // 2 + 1)) def is_difference_of_two_squares(n): return n % 4 != 2 def has_two_properties(locker_number): return ( sum(is_sum_of_two_primes(x) for x in istr.permutations(locker_number, join=True)) == 6 and sum(is_difference_of_two_squares(x) for x in istr.permutations(locker_number, join=True)) == 4 ) for my_locker_number in istr.range(102, 401, 3): if has_two_properties(my_locker_number) and has_two_properties(my_locker_number - 1): print("my locker number is", my_locker_number)LikeLike
Ruud van der Ham 9:49 am on 1 November 2026 Permalink |
This works because an integer can be expressed as a difference of two integer squares if and only if its remainder when divided by 4 is not 2.
LikeLiked by 1 person