#!/usr/local/bin/python3 from itertools import combinations, combinations_with_replacement from collections import Counter L=(1,2,3,4,6,7,8,9,10,11,12,13) def make_dist(xs): c=Counter({0:1}) for v in xs: vv=v if v<=9 else 10 p=Counter() for s in list(c): p[sum((s,vv))]=c[s] c.update(p) return c def seq3(ps): D=sorted(set(ps)) runs=[] start=None prev=None for v in D: if start is None: start=v elif v!=sum((prev,1)): runs.append((start,prev)) start=v prev=v if start is not None: runs.append((start,prev)) total=0 for a,b in runs: ln=len(range(a,sum((b,1)))) if ln>=3: ways=1 for lev in range(a,sum((b,1))): ways=ways*ps.count(lev) total=sum((total,ln*ways)) return total def build_good(): good=set() for a in combinations_with_replacement(range(1,11),5): d=make_dist(a) n15=d.get(15,0) ok=True for m in range(9,22): if d.get(m,0)>n15: ok=False if ok: good.add(tuple(a)) return good def aff(H,k): return tuple(sorted((v if v<=9 else 10 for v in (*H,k)))) def aligned_menus(good): out=[] for H in combinations(L,4): ok=True for k in range(1,14): if aff(H,k) not in good: ok=False if ok: out.append(H) return out def scores3(H,m): out=[] for k in range(1,14): ps=(*H,k) d=make_dist(ps) sc=sum((2*d.get(m,0),seq3(ps),(k in H)*2)) out.append(sc) return out def main(): good=build_good() print('goodcount',len(good)) cand=aligned_menus(good) print('candcount',len(cand)) print('cands',cand) rbest=None rt=[] for H in cand: ts=scores3(H,15) r=max(ts)-min(ts) print('chk',H,r,ts,sum(ts)) if rbest is None or r>rbest: rbest=r rt=[H] elif r==rbest: rt.append(H) print('selrange',rbest,'selcount',len(rt),'seltied',rt) main()