"""Complete regular fourth-row extension and compatibility graphs for 45 seeds. Exact modular graph equations; disconnected graphs retain free circle phases. """ from itertools import combinations,permutations,product from collections import Counter from pathlib import Path import json,time,sys from seeds import MOD,seeds BASE=Path(__file__).resolve().parent ALLOWED={'AAA','ACC','BBB','BCC','CCC'} def patterns(t): out=[] def add(groups): edges=[] for b,res,m in groups: for j,r in zip(b[1:],res[1:]):edges.append((j,b[0],r*(MOD//m))) out.append(tuple(edges)) if t=='A': for p in permutations(range(1,7)):add([(tuple(range(7)),(0,)+p,7)]) if t=='B': for pair in combinations(range(7),2): rest=tuple(j for j in range(7) if j not in pair) for p in permutations(range(1,5)):add([(rest,(0,)+p,5),(pair,(0,1),2)]) if t=='C': for tri in combinations(range(7),3): rest=[j for j in range(7) if j not in tri] for j in rest[1:]: pair=(rest[0],j);other=tuple(k for k in rest if k not in pair) for p in [(0,1,2),(0,2,1)]:add([(tri,p,3),(pair,(0,1),2),(other,(0,1),2)]) return out PAT={t:patterns(t) for t in 'ABC'} def block(row,b,m):return {(row[j]-row[b[0]])%MOD for j in b}==set(range(0,MOD,MOD//m)) def direct_type(row): if block(row,tuple(range(7)),7):return 'A',[[j+1 for j in range(7)]] for pair in combinations(range(7),2): if not block(row,pair,2):continue rest=tuple(j for j in range(7) if j not in pair) if block(row,rest,5):return 'B',[[j+1 for j in rest],[j+1 for j in pair]] for tri in combinations(range(7),3): if not block(row,tri,3):continue rest=[j for j in range(7) if j not in tri] for j in rest[1:]: pair=(rest[0],j);other=tuple(k for k in rest if k not in pair) if block(row,pair,2) and block(row,other,2):return 'C',[[k+1 for k in b] for b in (tri,pair,other)] return None,None def quotient(a,b):return [(x-y)%MOD for x,y in zip(a,b)] def assignments(rows): old={(i,j):direct_type(quotient(rows[i],rows[j]))[0] for i,j in combinations(range(3),2)} assert None not in old.values() return [''.join(t) for t in product('ABC',repeat=3) if all(''.join(sorted([old[i,j],t[i],t[j]])) in ALLOWED for i,j in old)],old class Graph: def __init__(self):self.p=list(range(7));self.c=[0]*7 def clone(self): q=Graph();q.p=self.p.copy();q.c=self.c.copy();return q def find(self,i): c=0 while i!=self.p[i]:c+=self.c[i];i=self.p[i] return i,c%MOD def add(self,i,j,c): a,x=self.find(i);b,y=self.find(j);c=(c-x+y)%MOD if a==b:return c==0 if a