Sunday Times Teaser 2752 – Best Before
by Nick MacKinnon
Published: 21 June 2015 (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 “nonsquare” pandigital time?
(b) When will that first “squaresum” pandigital time be?

Brian Gladman permalink1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859from datetime import datefrom functools import reducefrom operator import mulfrom number_theory import factor# for last 'nonsquare' time and first 'square' timensq_time, sq_time = None, None# select the month digits (include leading zero digits in numbers)for m in range(1, 13):set_m = set(str(m).zfill(2))if len(set_m) != 2:continue# select the hour digitsfor h in range(24):set_mh = set(str(h).zfill(2))  set_mif len(set_mh) != 4:continue# select the day digitsfor d in range(1, 32):# find the remaining digits for hour and minuteset_mny = set('0123456789')  (set(str(d).zfill(2))  set_mh)if len(set_mny) != 4:continue# select the minutes digitsfor mn in range(60):set_y = set_mny  set(str(mn).zfill(2))if len(set_y) != 2:continue# form the year value from the two remaining digitsa, b = (int(x) for x in set_y)for y in sorted((10 * a + b, 10 * b + a)):# the five numbers and their sum and productt = (y, m, d, h, mn)sm, prd = sum(t), reduce(mul, t, 1)# factor the product and extract the even prime exponents# (which will be empty if the product is 'square free')if not tuple((p, e // 2) for p, e in factor(prd) if e > 1):if not nsq_time or nsq_time < t:nsq_time = t + (1900 + y,)# check for a perfect squareif int(sm ** 0.5 + 0.5) ** 2 == sm:if not sq_time or sq_time > t:sq_time = t + (2000 + y,)# output the two datesfs = '{3:02d}:{4:02d} on {2:02d}/{1:02d}/{0:02d} ({5:04d})'print('(a)', fs.format(*nsq_time))print('(b)', fs.format(*sq_time))