#!/usr/bin/env python3
import sys,lzma,collections,glob,os

def read(path):
    op=lzma.open if path.endswith('.xz') else open
    with op(path,'rt',errors='ignore') as f:
        n=m=0; sizes=collections.Counter(); pos=neg=0; first=[]
        varpos=collections.Counter(); varneg=collections.Counter()
        clauses=[]
        for line in f:
            if not line or line[0]=='c': continue
            if line[0]=='p':
                parts=line.split(); n=int(parts[2]); m=int(parts[3]); continue
            lits=[int(x) for x in line.split() if x!='0']
            if not lits: continue
            sizes[len(lits)]+=1
            for l in lits:
                if l>0: pos+=1; varpos[l]+=1
                else: neg+=1; varneg[-l]+=1
            if len(first)<20: first.append(lits)
            clauses.append(lits)
        return n,m,sizes,pos,neg,varpos,varneg,clauses,first
for path in sys.argv[1:]:
    n,m,sizes,pos,neg,vp,vn,clauses,first=read(path)
    print('\n',os.path.basename(path), 'n',n,'m',m,'sizes',dict(sorted(sizes.items())),'pos/neg',pos,neg)
    # exact one groups: pos clause with all pairwise neg among lits
    negpairs=set()
    for c in clauses:
        if len(c)==2 and c[0]<0 and c[1]<0:
            a,b=sorted((-c[0],-c[1])); negpairs.add((a,b))
    groups=[]
    for c in clauses:
        if len(c)>1 and all(l>0 for l in c) and len(c)<=100:
            ok=True
            for i,a in enumerate(c):
                for b in c[i+1:]:
                    if (min(a,b),max(a,b)) not in negpairs:
                        ok=False; break
                if not ok: break
            if ok: groups.append(c)
    print('exact-one candidates',len(groups),'size dist',collections.Counter(map(len,groups)))
    print('first groups', [len(g) for g in groups[:10]], groups[:3])
    # Vars appearing in exact groups
    S=set(x for g in groups for x in g)
    print('vars in ex1',len(S),'range', (min(S),max(S)) if S else None, 'outside', n-len(S))
