#!/usr/bin/env python3
import sys, random, time, lzma

def read(path):
    op = lzma.open if path.endswith('.xz') else open
    n=0; clauses=[]
    with op(path,'rt') as f:
        for line in f:
            if not line or line[0] in 'c%0': continue
            if line[0]=='p': n=int(line.split()[2]); continue
            lits=[int(x) for x in line.split() if x!='0']
            if lits: clauses.append(lits)
    return n, clauses

def solve(n, clauses, secs=10):
    occ=[[] for _ in range(n+1)]
    for ci,c in enumerate(clauses):
        for lit in c: occ[abs(lit)].append((ci, lit>0))
    end=time.time()+secs
    rng=random.Random(1)
    tries=0
    while time.time()<end:
        tries+=1
        # false density tuned for W(3,k): sparse but enough to hit long APs
        p=rng.uniform(0.18,0.34)
        ass=[False]+[rng.random()>p for _ in range(n)]
        satcnt=[0]*len(clauses); uns=[]; pos=[-1]*len(clauses)
        for i,c in enumerate(clauses):
            s=0
            for lit in c:
                if ass[abs(lit)]==(lit>0): s+=1
            satcnt[i]=s
            if s==0: pos[i]=len(uns); uns.append(i)
        flips=0
        while uns and time.time()<end and flips<300000:
            flips+=1
            ci=uns[rng.randrange(len(uns))]
            c=clauses[ci]
            if rng.random()<0.08:
                v=abs(rng.choice(c))
            else:
                best=[]; bestscore=10**9
                sample=c if len(c)<=12 else rng.sample(c, min(len(c),12))
                for lit0 in sample:
                    v=abs(lit0); make=breaks=0
                    old=ass[v]
                    for cj,sign in occ[v]:
                        littrue = (old==sign)
                        if littrue:
                            if satcnt[cj]==1: breaks+=1
                        else:
                            if satcnt[cj]==0: make+=1
                    score=breaks-make
                    if score<bestscore: bestscore=score; best=[v]
                    elif score==bestscore: best.append(v)
                v=rng.choice(best)
            old=ass[v]; ass[v]=not old
            for cj,sign in occ[v]:
                was=(old==sign)
                if was:
                    if satcnt[cj]==1:
                        pos[cj]=len(uns); uns.append(cj)
                    satcnt[cj]-=1
                else:
                    if satcnt[cj]==0:
                        p0=pos[cj]; last=uns[-1]; uns[p0]=last; pos[last]=p0; uns.pop(); pos[cj]=-1
                    satcnt[cj]+=1
            if not uns:
                return ass, tries, flips
    return None, tries, 0

if __name__=='__main__':
    n,cls=read(sys.argv[1]); sol,tr,fl=solve(n,cls,float(sys.argv[2]) if len(sys.argv)>2 else 10)
    print('n',n,'m',len(cls),'sol',sol is not None,'tries',tr,'flips',fl)
