Teaser 2752: Best before
From The Sunday Times, 21st June 2015 [link] [link]
Peter likes to note “pandigital” times, such as 15.46, 29/03/78, that use all ten digits. Here the five individual numbers (15, 46, 29, 3 and 78) have a product that is divisible by the perfect square 36, and they also have a sum that is two more than a perfect square.
He has been watching for pandigital times ever since and remembers one where the product of the five numbers was not divisible by any perfect square (apart from 1): this has never happened since! He is also looking out for a pandigital time where the sum of the five numbers is a perfect square:
(a) When was that last “non-square” pandigital time?
(b) When will that first “square-sum” pandigital time be?
[teaser2752]














Jim Randell 8:51 am on 6 September 2022 Permalink |
We generate possible pandigital times, and then check to find the last (before the puzzle was set) with a square-free product, and the first (after the puzzle was set) with a perfect square sum.
This Python program runs in 70ms. (Internal runtime is 14.4ms).
from datetime import datetime from enigma import ( irange, choose, implies, nconcat, catch, multiply, is_square_free, is_square, printf ) # find pandigital (y, m, d, H, M) values def generate(): # possible digits digits = set(irange(0, 9)) # selection functions fns = [ # month first digit; is 0-1 lambda m1: m1 < 2, # hour first digit; is 0-2 lambda m1, H1: H1 < 3, # day first digit; is 0-3 lambda m1, H1, d1: d1 < 4, # minute first digit; is 0-5 lambda m1, H1, d1, M1: M1 < 6, # month second digit; m2 = 1 -> 0, 2 lambda m1, H1, d1, M1, m2: implies(m1 == 1, m2 < 3), # hour second digit; H1 = 2 -> 0, 1, 2 lambda m1, H1, d1, M1, m2, H2: implies(H1 == 2, H2 < 3), # day second digit; d1 = 3 -> 0, 1 lambda m1, H1, d1, M1, m2, H2, d2: implies(d1 == 3, d2 < 2), # remaining digits (M2, y1, y2) = any None, None, None ] # assign digits for (m1, H1, d1, M1, m2, H2, d2, M2, y1, y2) in choose(digits, fns, distinct=1): (y, m, d, H, M) = (nconcat(*x) for x in [(y1, y2), (m1, m2), (d1, d2), (H1, H2), (M1, M2)]) y += (2000 if y < 78 else 1900) t = catch(datetime, y, m, d, H, M) if t is not None: yield (t, (H, M, d, m, y % 100)) # date of the puzzle now = datetime(2015, 6, 21) # record answers a = b = None # look for pandigital times for (t, ns) in generate(): # (a) latest time before now with a square-free product if t < now and (a is None or t > a) and is_square_free(multiply(ns)): a = t # (b) earliest time after now with a perfect square sum if t > now and (b is None or t < b) and is_square(sum(ns)): b = t # output solution fmt = lambda t: t.strftime("%H:%M, %d/%m/%y") printf("(a) {a}", a=fmt(a)) printf("(b) {b}", b=fmt(b))Solution: (a) 15:43, 26/07/89; (b) 18:59, 27/06/34.
LikeLike
Frits 6:06 pm on 6 September 2022 Permalink |
Two programs:
from itertools import permutations # small numbers which are square free nums = [n for n in range(1, 32) if n % 11 and all(n % y for y in [4, 9, 25])] days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] mx_dt = 0 # check day/month/hour permutations for d, m, h in permutations(nums, 3): if m > 12 or h > 24: continue s = "".join(str(x).zfill(2) for x in (d, m, h)) if len(set(s)) != 6: continue # different digits p1 = d * m * h # product # not divisible by any perfect square if not all(p1 % (n * n) for n in [2] + list(range(3, int(p1**.5) + 1, 2))): continue # check day number if d > 28 and m == 2: if year % 4 == 0 and (year % 100 or year % 400 == 0): days[1] = 29 else: days[1] = 28 if d > days[m - 1]: continue rest = [int(x) for x in range(9, -1, -1) if str(x) not in s] mdh = str(m).zfill(2) + str(d).zfill(2) + str(h).zfill(2) # check year/minutes permutations for p in permutations(rest): if p[2] > 5: continue # minutes < 60 year = 10 * p[0] + p[1] if 15 < year < 78: continue # year between 1978 and 2015 mins = 10 * p[2] + p[3] # built date string dt = int(("19" if year > 77 else "20") + str(year) + mdh + str(mins)) if dt < mx_dt: continue # skip if earlier year than maximum # not divisible by any perfect square for new numbers ... p2 = mins * year if not all(p2 % (n * n) for n in [2] + list(range(3, int(p2**.5) + 1, 2))): continue # ... and for all five 2-digit numbers p2 *= p1 if not all(p2 % (n * n) for n in [2] + list(range(3, int(p2**.5) + 1, 2))): continue mx_dt = dt # new maximum break # as p is decreasing s = str(mx_dt) print(f"last 'non-square' pandigital time: " f"{s[6:8]}/{s[4:6]}/{s[:4]} {s[8:10]}:{s[10:]}")and
days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] # pick one value from each entry of a <k>-dimensional list <ns> # so that all digits in the <k> values are different def pickOneFromEach(k, ns, s=[], dgts=set()): if k == 0: yield s else: for n in ns[k - 1]: sn = str(n).zfill(2) if all(x not in dgts for x in sn): yield from pickOneFromEach(k - 1, ns, s + [sn], dgts | set(sn)) # months, days and hours have to use the digits 0, 1 and 2 # months 10 and 12 are invalid as they use two of the digits 0, 1 and 2 # and leave no room for day and hour so month < 10 ys = list(n for n in range(34, 100) if n % 11 and all(y not in str(n) for y in "012")) ms = list(range(1, 10)) ds = list(n for n in range(13, 32) if n % 11 and n % 10) hs = list(n for n in range(24) if n % 11 and n % 10) mis = list(n for n in range(34, 60) if n % 11 and all(y not in str(n) for y in "012")) rev_lst = [mis, hs, ds, ms, ys] for p in pickOneFromEach(5, rev_lst): s = "".join(p) # sum has to be a perfect square if sum([int(x) for x in p]) not in {144, 169, 196}: continue # check day number m, d = (int(p[1]), int(p[2])) if d > 28 and m == 2: if year % 4 == 0 and (year % 100 or year % 400 == 0): days[1] = 29 else: days[1] = 28 if d > days[m - 1]: continue print(f" first 'square-sum' pandigital time: " f"{p[2]}/{p[1]}/{p[0]} {p[3]}:{p[4]}") break # we have found the first dateLikeLike