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


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


def read_cnf(path):
    nvars = nclauses = None
    clauses = []
    with open_cnf(path) as f:
        cur = []
        for line in f:
            if not line or line[0] == "c":
                continue
            if line[0] == "p":
                parts = line.split()
                nvars, nclauses = int(parts[2]), int(parts[3])
                continue
            for tok in line.split():
                lit = int(tok)
                if lit == 0:
                    if cur:
                        clauses.append(tuple(cur))
                        cur = []
                else:
                    cur.append(lit)
    return nvars, nclauses, clauses


def summarize(path):
    nvars, nclauses, clauses = read_cnf(path)
    sizes = collections.Counter(map(len, clauses))
    pos = neg = 0
    deg = [0] * (nvars + 1)
    pol = [0] * (nvars + 1)
    first_occ = [None] * (nvars + 1)
    last_occ = [None] * (nvars + 1)
    for ci, cl in enumerate(clauses):
        for lit in cl:
            v = abs(lit)
            deg[v] += 1
            pol[v] += 1 if lit > 0 else -1
            if lit > 0:
                pos += 1
            else:
                neg += 1
            if first_occ[v] is None:
                first_occ[v] = ci
            last_occ[v] = ci
    deg_count = collections.Counter(deg[1:])
    span_count = collections.Counter((last_occ[v] - first_occ[v] + 1) if first_occ[v] is not None else 0 for v in range(1, nvars + 1))
    horn = sum(1 for cl in clauses if sum(1 for lit in cl if lit > 0) <= 1)
    anti_horn = sum(1 for cl in clauses if sum(1 for lit in cl if lit < 0) <= 1)
    print(f"{Path(path).name}: vars={nvars} clauses={len(clauses)}/{nclauses} sizes={dict(sorted(sizes.items()))} pos={pos} neg={neg} horn={horn} anti_horn={anti_horn}")
    print("  deg top:", deg_count.most_common(12))
    print("  span top:", span_count.most_common(12))
    print("  first 30 clauses:")
    for i, cl in enumerate(clauses[:30], 1):
        print(f"    {i:5d}: {' '.join(map(str, cl))}")
    print("  last 20 clauses:")
    for i, cl in enumerate(clauses[-20:], len(clauses) - 19):
        print(f"    {i:5d}: {' '.join(map(str, cl))}")


def main(argv):
    for path in argv[1:]:
        summarize(path)


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