elsewhere. So its largely a matter of personal choice. The interleaving

of inhomogeneous data (years and year differences) in a list is another

such approach that is largely the same although I tend to avoid it. ]]>

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
from number_theory import is_prime # prime years in the twentieth century except 1973 p20 = tuple(x for x in range (1901, 2001, 2) if is_prime(x) and x != 1973) # prime years in the nineteenth century: start point of first PM # 1870 ~ 1900 - 29 (largest prime ministerial term) p19 = tuple(x for x in range(1871, 1900, 2) if is_prime(x)) # possible lengths of PMs' years in office + 1 for odd primes (primes < 30) p30 =(2, 4, 6, 8, 12, 14, 18, 20, 24, 30) # We define twentieth century as being from from 1900 through the end of 1999 # In which case the first prime minister starts in the 19th century # because 1900 is not prime, last prime minister's term ends on the last day of # the twentieth century (1999 is prime) or overlaps into the 21st century. # pl : primes left; loy : list of years def findpm(pl, loy): # last PM of 9 must end on Dec 31, 1999 or overlap into 21st century if len(loy) == 9 and loy[-1] + max(pl) >= 1999: yield loy # consider the prime ministerial term lengths left for i, p in enumerate(pl): # when p = 2; term is exactly 2 years # for odd prime p, term = p + 11 months + x days, then max 1 month gap # does final year + a prime term under 30 + 1 reach a new prime year? if loy[-1] + p in p20: yield from findpm(pl[:i] + pl[i + 1:], loy + (loy[-1] + p,)) # consider 19th century start year for first PM for pmstart in p19: # with pmstart as first year, try to find the 9 PMs for pms in findpm(p30, (pmstart,)): print(str(pms)[1: -1]) |

1 2 3 |
for pms in findpm(pmstart, p30, (pmstart,)): |

I have rewritten my code to avoid doing this. See below after GeoffR’s entry.

]]>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
from number_theory import is_prime # prime years in the twentieth century except 1973 p20 = tuple(x for x in range (1901, 2001, 2) if is_prime(x) and x != 1973) # prime years in the nineteenth century: start point of first PM # 1870 ~ 1900 - 29 (largest prime ministerial term) p19 = tuple(x for x in range(1871, 1900, 2) if is_prime(x)) # possible lengths of PMs' years in office + 1 for odd primes (primes < 30) p30 =(2, 4, 6, 8, 12, 14, 18, 20, 24, 30) # We define twentieth century as being from from 1900 through the end of 1999 # In which case the first prime minister starts in the 19th century # because 1900 is not prime, last prime minister ends in 21st century def findpm(year, primesleft, list_of_years): # last PM of 9 must overlap into 21st century if len(list_of_years) == 9 and year + max(primesleft) >= 2000: yield list_of_years for i, p in enumerate(primesleft): # when p = 2; term is exactly 2 years # for odd prime p, term = p + 11 months + x days, then max 1 month gap if year + p in p20: yield from findpm(year + p, primesleft[:i] + primesleft[i + 1:], list_of_years + (year + p,)) # consider 19th century start year for first PM for pmstart in p19: # with pmstart as first year, try to find the 9 PMs for pms in findpm(pmstart, p30, (pmstart,)): print(str(pms)[1: -1]) |

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
from itertools import combinations from number_theory import is_prime # possible first years for the 2nd and subsequent Prime Ministers pyrs = years = list(n for n in range(1901, 2000) if is_prime(n) and n != 1973) # possible prime gaps not more than thirty pgps = {g for g in range(1, 31) if is_prime(g)} # consider the first year for the first Prime Minister # (1901 at the latest) ... for pm1 in (n for n in range(1870, 1902) if is_prime(n)): # ... and then the first years for the subsequent eight for pms8 in combinations(pyrs, 8): if not pm1 < pms8[0]: continue pms9 = (pm1,) + pms8 # find the number of years between Prime Ministers gaps = {pms9[i] - v for i, v in enumerate(pms9[:-1], 1)} # find the prime gaps for this set of years - there # must be eight, all different pgp8 = {pg for g in gaps for pg in pgps & {g, g - 1}} if len(pgp8) == 8: # check that the last Prime Minister's term is possible if (r := pgps.difference(pgp8)): print(f"{' '.join(str(n) for n in pms9)}") print(f" {' '.join(f'{str(n):5}' for n in pgp8)} " f"({' / '.join(str(n) for n in sorted(r))})") |

Recursion is faster

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
from number_theory import is_prime # possible first years for the 2nd and subsequent Prime Ministers pyrs = years = list(n for n in range(1901, 2000) if is_prime(n) and n != 1973) # possible prime gaps not more than thirty pgps = {g for g in range(1, 31) if is_prime(g)} # find <n> years from <yrs> such that 'whole year' gaps between # successive years are prime and less than or equal to 30 def solve(n, yrs, yseq, gseq=()): if not n: # the last PM cannot serve for more than 30 years if yseq[-1] >= 1969: yield yseq, gseq else: # add a year with a prime 'whole year' gap for i, y in enumerate(yrs): g = y - yseq[-1] for g in pgps & {g, g - 1}: if g not in gseq: yield from solve(n - 1, yrs[i + 1:], yseq + (y,), gseq + (g,)) # consider the first year for the first Prime Minister # (1901 at the latest) ... for pm1 in (n for n in range(1870, 1902) if is_prime(n)): # solve for the remaining eight Prime Ministers for pms9, pgp8 in solve(8, pyrs, (pm1,)): # check that the last Prime Minister's term is possible if (r := pgps.difference(pgp8)): print(f"{' '.join(str(n) for n in pms9)}") print(f" {' '.join(f'{str(n):5}' for n in pgp8)} " f"({' / '.join(str(n) for n in sorted(r))})") |

1 2 3 |
if len(list_of_years) == 17 and year <= 2000: |