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


def open_dimacs(path: Path):
    if path.suffix == ".xz":
        return lzma.open(path, "rt", encoding="ascii")
    return path.open("rt", encoding="ascii")


def parse(path: Path):
    nvars = 0
    clauses = []
    with open_dimacs(path) as f:
        pending = []
        for line in f:
            if not line or line[0] == "c":
                continue
            if line[0] == "p":
                nvars = int(line.split()[2])
                continue
            for tok in line.split():
                lit = int(tok)
                if lit == 0:
                    clauses.append(tuple(pending))
                    pending = []
                else:
                    pending.append(lit)
    return nvars, clauses


def propagate(nvars, clauses):
    occ = [[] for _ in range(2 * nvars + 2)]

    def idx(lit):
        v = abs(lit)
        return 2 * v + (lit < 0)

    for ci, cl in enumerate(clauses):
        for lit in cl:
            occ[idx(lit)].append(ci)

    assign = [0] * (nvars + 1)
    q = collections.deque()
    reasons = [None] * (nvars + 1)
    conflict = None
    for ci, cl in enumerate(clauses):
        if len(cl) == 1:
            lit = cl[0]
            v = abs(lit)
            val = 1 if lit > 0 else -1
            if assign[v] == -val:
                conflict = ci
                break
            if assign[v] == 0:
                assign[v] = val
                reasons[v] = ci
                q.append(lit)
    props = 0
    scans = 0
    while conflict is None and q:
        lit = q.popleft()
        for ci in occ[idx(-lit)]:
            scans += 1
            cl = clauses[ci]
            sat = False
            un = 0
            last = 0
            for x in cl:
                a = assign[abs(x)]
                if a == 0:
                    un += 1
                    last = x
                elif (a > 0) == (x > 0):
                    sat = True
                    break
            if sat:
                continue
            if un == 0:
                conflict = ci
                break
            if un == 1:
                v = abs(last)
                val = 1 if last > 0 else -1
                if assign[v] == -val:
                    conflict = ci
                    break
                if assign[v] == 0:
                    assign[v] = val
                    reasons[v] = ci
                    q.append(last)
                    props += 1
    assigned = sum(1 for x in assign[1:] if x)
    return assigned, props, scans, conflict, assign, reasons


def main():
    for arg in sys.argv[1:]:
        path = Path(arg)
        nvars, clauses = parse(path)
        assigned, props, scans, conflict, _assign, _reasons = propagate(nvars, clauses)
        print(
            f"{path.name}: vars={nvars} clauses={len(clauses)} "
            f"assigned={assigned} implied={props} scans={scans} "
            f"conflict={'none' if conflict is None else conflict}"
        )


if __name__ == "__main__":
    main()
