"""Iteratively kill tight splits with exact per-split maxima until the counting DP is infeasible.
Usage: python3 close.py n t [max_a_min]   (split3c handles a >= 22; we only attempt splits with a >= 22)"""
import sys, subprocess, re, os
from math import comb
from collections import Counter
from fractions import Fraction as Fr
import deeper, bound
from bound import partitions, U, g

n, t = int(sys.argv[1]), int(sys.argv[2])
killed_file = f"killed_{n}_{t}.txt"
killed = set(eval(l) for l in open(killed_file)) if os.path.exists(killed_file) else set()
results = {p: -1 for p in killed}
if killed: print("resuming; already killed:", sorted(killed))

def reps_file(b, minL):
    fn = f"s1_n{n}_{b}_{minL}_reps.txt"
    if not os.path.exists(fn):
        with open(fn, "w") as f:
            p1 = subprocess.Popen(["./cands3", str(b), str(minL)], stdout=subprocess.PIPE)
            p2 = subprocess.Popen(["./canon"], stdin=p1.stdout, stdout=subprocess.PIPE)
            out = p2.communicate()[0].decode()
            f.write("\n".join(sorted(set(l.strip() for l in out.split("\n") if l.strip()))) + "\n")
    return fn

def exact_max(p):
    a, b, c = p
    Tmax = min(a * b, b * c, c * a)
    minL1 = t - g[a] - g[c] - Tmax
    args = ["./split3c", str(a), str(b), str(c), str(t)]
    if b >= 11:
        args.append(reps_file(b, minL1))
    out = subprocess.run(args, capture_output=True, text=True, timeout=1500).stdout
    m = re.search(r"exact max L = (-?\d+)", out)
    return int(m.group(1)), out.strip().split("\n")[0]

while True:
    adm = [p for p in partitions(n) if U(p) >= t and p not in killed]
    v, ms = deeper.dp_max(n, t, adm)
    if v is None or v < 18 * t + 9 * comb(n, 3):
        print(f"n={n}: INFEASIBLE at L={t} after killing {sorted(killed)} -> f({n}) <= {t-1}")
        break
    cnt = Counter(ms)
    print(f"n={n} t={t}: feasible, implied L={Fr(v - 9*comb(n,3), 18)}; phantom {sorted(cnt.items(), reverse=True)}")
    # candidates to kill: splits in the phantom with a >= 22, by slack
    cands = sorted([(U(p) - t, p) for p in cnt if p[0] >= 22 and p not in results])
    if not cands:
        print("no further killable splits (all remaining phantom splits have a < 22 or were already tested)"); break
    slack, p = cands[0]
    mx, hdr = exact_max(p)
    results[p] = mx
    print(f"   tested {p} (slack {slack}): {hdr}\n   -> exact max {mx} {'< t: KILLED' if mx < t else '>= t: SURVIVES (method stuck)'}", flush=True)
    if mx < t:
        killed.add(p); open(killed_file, "a").write(repr(p) + "\n")
    else: break
