#!/usr/bin/env python3
import lzma
import sys
from pathlib import Path


def open_cnf(path):
    return lzma.open(path, "rt") if str(path).endswith(".xz") else open(path)


def read(path):
    clauses = []
    n = m = 0
    with open_cnf(path) as f:
        cur = []
        for line in f:
            if not line or line[0] == "c":
                continue
            if line[0] == "p":
                _, _, n, m = line.split()[:4]
                n, m = int(n), int(m)
            else:
                for tok in line.split():
                    x = int(tok)
                    if x == 0:
                        if cur:
                            clauses.append(tuple(cur))
                            cur = []
                    else:
                        cur.append(x)
    return n, clauses


def gate3(cl1, cl2, cl3):
    # Detect the exact edit-distance generator's 3-clause block:
    # (-a -b c), (-a b -c), (a -b -c), in this order.
    if len(cl1) == len(cl2) == len(cl3) == 3:
        a = -cl1[0]
        b = -cl1[1]
        c = cl1[2]
        if a > 0 and b > 0 and c > 0 and cl2 == (-a, b, -c) and cl3 == (a, -b, -c):
            return a, b, c
    return None


def main(argv):
    n, clauses = read(argv[1])
    runs = []
    i = 0
    gates = []
    while i + 2 < len(clauses):
        g = gate3(clauses[i], clauses[i + 1], clauses[i + 2])
        if not g:
            i += 1
            continue
        start = i
        cur = []
        while i + 2 < len(clauses):
            g = gate3(clauses[i], clauses[i + 1], clauses[i + 2])
            if not g:
                break
            cur.append((i // 3 + 1, *g))
            gates.append((i, *g))
            i += 3
        runs.append((start + 1, len(cur), cur[0], cur[-1]))
    print(Path(argv[1]).name, "vars", n, "clauses", len(clauses), "gate3", len(gates), "runs", len(runs))
    print("runs:")
    for r in runs[:40]:
        print(" ", r)
    if len(runs) > 40:
        print(" ...")
    # print breakpoints and first clauses after each long run
    for start, length, first, last in runs[:20]:
        if length >= 5:
            idx = start - 1 + length * 3
            print(f"after run at clause {start} len {length}, next {idx+1}:")
            for j in range(idx, min(idx + 8, len(clauses))):
                print(" ", j + 1, clauses[j])


if __name__ == "__main__":
    main(sys.argv)
