import sys,lzma,random,time,heapq,math
from collections import defaultdict,Counter

def read(path):
    op = lzma.open if path.endswith('.xz') else open
    clauses=[]; units=[]; n=m=0
    with op(path,'rt') as f:
        for line in f:
            if not line or line[0]=='c': continue
            if line[0]=='p':
                p=line.split(); n=int(p[2]); m=int(p[3]); continue
            lits=list(map(int,line.split()))
            if not lits: continue
            if lits[-1]==0: lits=lits[:-1]
            clauses.append(lits)
    cover=[c for c in clauses if len(c)>4 and all(x>0 for x in c)]
    primary=max(max(c) for c in cover)
    unit=[c[0] for c in clauses if len(c)==1]
    outs=sorted([abs(u) for u in unit if abs(u)>primary])
    bits=[]
    for v in outs:
        s=1 if v in unit else 0
        bits.append(s)
    k=sum(b<<i for i,b in enumerate(bits))
    return n,primary,k,cover,unit

def greedy(primary,k,cover):
    uncovered=set(range(len(cover)))
    occ=[set() for _ in range(primary+1)]
    for i,c in enumerate(cover):
        for v in c:
            if v<=primary: occ[v].add(i)
    heap=[]
    for v in range(1,primary+1):
        if occ[v]: heapq.heappush(heap,(-len(occ[v]),v))
    sel=[]
    while uncovered and len(sel)<k:
        while heap:
            neg,v=heapq.heappop(heap); gain=len(occ[v]&uncovered)
            if gain==-neg: break
            heapq.heappush(heap,(-gain,v))
        else: break
        if gain==0: break
        sel.append(v); uncovered-=occ[v]
    return sel,uncovered,occ

def local(primary,k,cover,seed=1,deadline=10):
    random.seed(seed)
    occ=[[] for _ in range(primary+1)]
    for i,c in enumerate(cover):
        for v in c: occ[v].append(i)
    sel,uncovered,occsets=greedy(primary,k,cover)
    # pad high degree
    selected=set(sel)
    deg=sorted(range(1,primary+1), key=lambda v: len(occ[v]), reverse=True)
    for v in deg:
        if len(selected)>=k: break
        selected.add(v)
    # try stochastic repair not needed maybe
    return selected, [i for i,c in enumerate(cover) if not any(v in selected for v in c)]

for path in sys.argv[1:]:
    n,p,k,cover,unit=read(path)
    sel,unc=local(p,k,cover)
    print(path.split('/')[-1], 'n',n,'primary',p,'k',k,'cover_clauses',len(cover),'sel',len(sel),'uncovered',len(unc), 'minlen',min(map(len,cover)), 'maxlen',max(map(len,cover)))
