#!/usr/bin/env python3
"""Generate or independently verify the complete 8-, 10-, and 12-cell lists.

Uses Python 3's standard library. Run beside the downloaded text files.
"""

import argparse
from itertools import combinations, product
from pathlib import Path


COUNTS = {8: 34, 10: 84, 12: 208}


def balanced_patterns(size):
    """Choose the positions of the ones, then reject triples."""
    rows = []
    for positions in combinations(range(size), size // 2):
        ones = set(positions)
        row = "".join("1" if index in ones else "0" for index in range(size))
        if "000" not in row and "111" not in row:
            rows.append(row)
    return sorted(rows)


def exhaustive_patterns(size):
    """Check every binary string with a separate, position-based predicate."""
    rows = []
    for cells in product("01", repeat=size):
        if cells.count("0") != size // 2:
            continue
        if any(cells[i] == cells[i + 1] == cells[i + 2] for i in range(size - 2)):
            continue
        rows.append("".join(cells))
    return rows


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--write", action="store_true", help="generate the text files")
    parser.add_argument("--directory", type=Path, default=Path(__file__).resolve().parent)
    args = parser.parse_args()
    for size, expected_count in COUNTS.items():
        rows = balanced_patterns(size)
        if rows != exhaustive_patterns(size) or len(rows) != expected_count:
            raise SystemExit(f"FAIL independent enumeration for {size} cells")
        filename = args.directory / f"binary-puzzle-row-patterns-{size}.txt"
        if args.write:
            filename.write_text("\n".join(rows) + "\n", encoding="utf-8")
        downloaded = filename.read_text(encoding="utf-8").splitlines()
        if downloaded != rows:
            raise SystemExit(f"FAIL {filename.name} has missing, extra, or reordered rows")
        print(f"PASS {size} cells / {len(rows)} patterns / two enumerations agree")


if __name__ == "__main__":
    main()
