#!/usr/bin/env python3
import sys,lzma,collections,itertools,math
fn=sys.argv[1]
openf=lzma.open if fn.endswith('.xz') else open
clauses=[]; n=m=0
with openf(fn,'rt') as f:
  for line in f:
    if not line or line[0] in 'c%0': continue
    parts=line.split()
    if not parts: continue
    if parts[0]=='p': n=int(parts[2]); m=int(parts[3]); continue
    lits=list(map(int,parts));
    if lits and lits[-1]==0: lits=lits[:-1]
    clauses.append(lits)
print('file',fn,'vars',n,'clauses',len(clauses))
print('sizes',collections.Counter(map(len,clauses)))
# infer support size from first 4 clauses
print('first lens/lits',[(len(c),c[:5],c[-5:]) for c in clauses[:6]])
base=None
if len(clauses)>=4 and len(clauses[0])==1 and len(clauses[2])==1:
  N=clauses[2][0]-1
  print('N infer',N,'base2N',2*N)
  base=2*N
# gate triples
bin_by_neg=collections.defaultdict(list); tern_by_pos=collections.defaultdict(list)
for c in clauses:
  if len(c)==2:
    neg=[-x for x in c if x<0]; pos=[x for x in c if x>0]
    if len(neg)==1 and len(pos)==1:
      bin_by_neg[neg[0]].append(pos[0])
  elif len(c)==3:
    neg=[-x for x in c if x<0]; pos=[x for x in c if x>0]
    if len(neg)==2 and len(pos)==1:
      tern_by_pos[pos[0]].append(tuple(sorted(neg)))
ands=[]
for z,ps in bin_by_neg.items():
  if len(ps)>=2:
    for pair in itertools.combinations(sorted(ps),2):
      if pair in tern_by_pos.get(z,[]):
        ands.append((z,pair[0],pair[1])); break
print('ANDs',len(ands),'first',ands[:5],'last',ands[-5:])
if base:
  above=[a for a in ands if a[0]>base]
  pairs=[(a,b) for z,a,b in above]
  print('AND z minmax',min(z for z,_,_ in above),max(z for z,_,_ in above),'baseANDs',len(above))
  # count pairs with a in first block and b in second
  cross=sum(1 for z,a,b in above if 1<=a<=N and N+1<=b<=2*N)
  print('cross',cross,'expected N2',N*N)
# non-gate clauses after removing gate triples rough classify by size and sign counts
and_clause_ids=set()
for z,a,b in ands:
  and_clause_ids.add(tuple(sorted([-z,a])))
  and_clause_ids.add(tuple(sorted([-z,b])))
  and_clause_ids.add(tuple(sorted([-a,-b,z])))
rem=[]
for c in clauses:
  if tuple(sorted(c)) not in and_clause_ids:
    rem.append(c)
print('rem count sizes',len(rem),collections.Counter(map(len,rem)))
print('rem sign/sizes',collections.Counter((len(c),sum(1 for x in c if x>0),sum(1 for x in c if x<0)) for c in rem).most_common(20))
print('rem examples after first 4')
for c in rem[:20]: print(c[:20], 'len', len(c))
