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

def read(path):
    f=lzma.open(path,'rt') if path.endswith('.xz') else open(path)
    n=0; cs=[]
    with f:
        cur=[]
        for line in f:
            if not line or line[0] in 'c%': continue
            if line[0]=='p': n=int(line.split()[2]); continue
            for t in line.split():
                l=int(t)
                if l==0:
                    if cur: cs.append(tuple(cur)); cur=[]
                else: cur.append(l)
    return n,cs

def bits_twos(v,w):
    if v<0: v=(1<<w)+v
    return [(v>>i)&1 for i in range(w)]

def propagate(n, clauses, assign):
    occ=[[] for _ in range(2*n+2)]
    def idx(l): return l+n
    for ci,c in enumerate(clauses):
        for l in c: occ[idx(l)].append(ci)
    q=collections.deque([l if val else -l for l,val in assign.items()])
    while q:
        lit=q.popleft(); v=abs(lit); val=lit>0
        if v in assign and assign[v]!=val: return False, assign
        assign[v]=val
        for ci in occ[idx(-lit)]:
            c=clauses[ci]; un=0; last=0; sat=False
            for l in c:
                av=assign.get(abs(l))
                if av is None:
                    un+=1; last=l
                elif av==(l>0):
                    sat=True; break
            if sat: continue
            if un==0:
                print('conflict clause',ci,c)
                return False, assign
            if un==1:
                v=abs(last); val=last>0
                old=assign.get(v)
                if old is not None and old!=val: return False, assign
                if old is None:
                    assign[v]=val; q.append(last)
    return True, assign

path=sys.argv[1]; vals=list(map(int,sys.argv[2:5]))
n,cs=read(path)
w=len(cs[0])
ass={}
for b,v in enumerate(vals):
    for i,bit in enumerate(bits_twos(v,w)):
        ass[b*w+i+1]=bool(bit)
ok,ass=propagate(n,cs,ass)
bad=0; uns=0
if ok:
    for c in cs:
        s=False; u=False
        for l in c:
            av=ass.get(abs(l))
            if av is None: u=True
            elif av==(l>0): s=True; break
        if not s:
            if u: uns+=1
            else: bad+=1
print('w',w,'ok',ok,'assigned',len(ass),'bad',bad,'unsat/unassigned clauses',uns)
