Brain-Teaser 12: [Birthdays]
From The Sunday Times, 14th/21st May 1961 [link] [link]
My wife and I, my son and daughter, my two grandsons, and my granddaughter (the youngest of the family, who was fifteen last birthday) were all born on the same day of the week, and we all have our birthdays on the same date, but all in different months. [I won’t be able to say this if there are any further additions to the family.]
My grandsons were born nine months apart, my daughter eighteen months after my son, and I am forty-one months older than my wife.
What are all our birth dates?
This puzzle was originally published in the 14th May 1961 edition of The Sunday Times, however the condition in square brackets was omitted, and the corrected version (and an apology) was published in the 21st May 1961 edition.
This puzzle was originally published with no title.
[teaser12]
Jim Randell 11:18 am on 1 November 2020 Permalink |
I assume the missing condition means that it is not possible for an 8th member of the family to have the same “day of week” and “day of month” birthday, but not share a birthday month with one of the group of 7.
The current calendar repeats itself every 400 years, so this program looks for sets of dates in a 400 years span that share the same “day of week” and “day of month” values, but that only involve 7 different months. (So that any further additions to the family could not be born of the same day of the week and day of the month, but a month that has not yet been used. (The condition that was missing when the puzzle was originally published)).
It then looks for dates that satisfy the required differences, and checks the all use different months.
It runs in 199ms.
Run: [ @repl.it ]
import datetime from enigma import group, catch, printf # generate dates between years a and b def dates(a, b): d = datetime.date(a, 1, 1) i = datetime.timedelta(days=1) while d.year < b: yield d d += i # the date n months earlier than d def earlier(d, n): (yy, mm, dd) = (d.year, d.month, d.day) (y, m) = divmod(mm - n - 1, 12) return catch(datetime.date, yy + y, m + 1, dd) # group 400 years of dates by (<day of week>, <day of month>) d = group(dates(1850, 2250), by=(lambda d: (d.weekday(), d.day))) # now look for keys that involve exactly 7 different months for ((dow, dom), vs) in d.items(): ms = set(d.month for d in vs) if len(ms) != 7: continue # collect possible birthdates for the granddaughter (gda, gdb) = (datetime.date(1945, 5, 15), datetime.date(1946, 5, 14)) for gdd in vs: if gdd < gda: continue if not(gdd < gdb): break # find birthdates for the grandsons (earlier than gd) for gsd2 in vs: if not(gsd2 < gdd): break gsd1 = earlier(gsd2, 9) if gsd1 is None or gsd1 not in vs: continue # find birthdates for the son and daughter (earlier than gs1 - 15 years) dx = gsd1 - datetime.timedelta(days=5479) for dd in vs: if not(dd < dx): break sd = earlier(dd, 18) if sd is None or sd not in vs: continue # find birthdates for the husband and wife (earlier than sd - 15 years) wx = sd - datetime.timedelta(days=5479) for wd in vs: if not(wd < wx): break hd = earlier(wd, 41) if hd is None or hd not in vs: continue # check the months are all different if len(set(d.month for d in (gdd, gsd2, gsd1, dd, sd, wd, hd))) != 7: continue printf("{dow} {dom}", dow=["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][dow]) printf("-> husband = {hd}, wife = {wd}") printf("-> son = {sd}, daughter = {dd}") printf("-> grandsons = {gsd1}, {gsd2}") printf("-> granddaughter = {gdd}") printf()Solution: The birthdates are all Mondays. The full list is (by generation):
The only “day of month” that allows exactly 7 months to be used is the 31st of the month, as there are only 7 months that have 31 days.
LikeLike