{"challengeId":"superperm-7","entry":"verifier.mjs","sha256":"9650ac6e68e0b37c0b4747d3c6aa59620a5375b6256f0acb9ce445fc61bfb274","scoreDirection":"minimize","scoreLabel":"symbols","seedPolicy":{"mode":"fixed","testCount":5040},"source":"// Frozen verifier for superperm-7. Self-contained (no imports): it reads the\n// candidate's superpermutation artifact and returns a Verdict. It never executes\n// agent code — build() already ran in the sandbox and handed us plain data.\n// This file is part of the challenge's PROTECTED surface.\n//\n// A superpermutation on the symbols {1..7} is a string in which every one of the\n// 7! = 5040 distinct permutations of those symbols appears as a contiguous\n// length-7 substring. The score is the string's length; shorter is better.\n//\n// Correctness is PROVEN, not sampled: we slide a length-7 window across the whole\n// string, and for every window that is itself a permutation of {1..7} we record\n// which permutation it is. We then assert that all 5040 permutations were seen.\n// Everything here is pure integer / string work and runs in O(L) where L is the\n// string length, so the check finishes far under the timeout on the bounded\n// instance. There is nothing for an agent to overfit to: the requirement is the\n// full, exhaustive set of permutations.\n\nconst N = 7; // symbols 1..7\nconst FACT = 5040; // 7! permutations that must all appear\nconst MAX_LEN = 60000; // hard bound on candidate length (rejects runaway artifacts)\n\nfunction gate(name, pass, detail) {\n  return { name, pass, detail };\n}\nfunction bad(name, detail) {\n  return { ok: false, score: null, gates: [gate(name, false, detail)], behavior: {}, logs: [] };\n}\n\n// Lehmer-code rank of a permutation given as an array of the symbols 1..N (each\n// exactly once). Pure integer arithmetic — multiply/add only, no transcendentals.\n// Returns a unique index in [0, N!-1] so we can mark seen permutations in a flat\n// array without hashing strings.\nfunction rank(perm, factorial) {\n  let r = 0;\n  // seen[v] = whether symbol value v (1..N) already consumed to its left\n  const used = new Array(N + 1).fill(false);\n  for (let pos = 0; pos < N; pos++) {\n    const v = perm[pos];\n    // count how many still-unused symbols are smaller than v\n    let smaller = 0;\n    for (let w = 1; w < v; w++) if (!used[w]) smaller++;\n    used[v] = true;\n    r += smaller * factorial[N - 1 - pos];\n  }\n  return r;\n}\n\nexport function verify(ctx) {\n  const sol = ctx && ctx.solution;\n  if (!sol || typeof sol !== 'object') {\n    return bad('structure', 'expected { perm: \"<digits 1..7>\" } or { perm: [ints] }');\n  }\n\n  // Accept either a string of digits or an integer array; normalize to an\n  // integer array `digits` of symbol values, each in 1..N.\n  let digits;\n  const p = sol.perm;\n  if (typeof p === 'string') {\n    const len = p.length;\n    if (len === 0) return bad('structure', 'perm string is empty');\n    if (len > MAX_LEN) return bad('bound', `length ${len} exceeds bound ${MAX_LEN}`);\n    digits = new Array(len);\n    for (let i = 0; i < len; i++) {\n      const code = p.charCodeAt(i) - 48; // '1'..'7' -> 1..7\n      if (code < 1 || code > N) {\n        return bad('alphabet', `character at index ${i} is not a digit 1..${N}`);\n      }\n      digits[i] = code;\n    }\n  } else if (Array.isArray(p)) {\n    const len = p.length;\n    if (len === 0) return bad('structure', 'perm array is empty');\n    if (len > MAX_LEN) return bad('bound', `length ${len} exceeds bound ${MAX_LEN}`);\n    digits = new Array(len);\n    for (let i = 0; i < len; i++) {\n      const v = p[i];\n      if (!Number.isInteger(v) || v < 1 || v > N) {\n        return bad('alphabet', `element at index ${i} is not an integer 1..${N}`);\n      }\n      digits[i] = v;\n    }\n  } else {\n    return bad('structure', 'perm must be a string of digits or an array of integers');\n  }\n\n  const L = digits.length;\n  if (L < N) {\n    return bad('length', `string of length ${L} is too short to contain any length-${N} permutation`);\n  }\n\n  // Precompute factorials 0!..(N-1)! for the Lehmer rank (pure integer).\n  const factorial = new Array(N);\n  factorial[0] = 1;\n  for (let k = 1; k < N; k++) factorial[k] = factorial[k - 1] * k;\n\n  // Slide a length-N window across the string. A window is a permutation of\n  // {1..N} iff all N symbols are distinct (each value 1..N appears exactly once);\n  // since values are already constrained to 1..N, \"all distinct\" suffices.\n  const seen = new Uint8Array(FACT); // seen[rank] = 1 once that permutation appears\n  let distinctCount = 0;\n  const winCount = new Int32Array(N + 1); // multiplicity of each value in current window\n  const window = new Array(N);\n\n  // Returns true if the current window (digits[start..start+N-1]) is a permutation.\n  // We maintain distinctCount incrementally so each step is O(1) amortized; the\n  // total scan is O(L).\n  for (let i = 0; i < L; i++) {\n    const incoming = digits[i];\n    if (winCount[incoming] === 0) distinctCount++;\n    winCount[incoming]++;\n    if (i >= N) {\n      const outgoing = digits[i - N];\n      winCount[outgoing]--;\n      if (winCount[outgoing] === 0) distinctCount--;\n    }\n    if (i >= N - 1) {\n      // window covers digits[i-N+1 .. i]; it is a permutation iff all N distinct\n      if (distinctCount === N) {\n        const base = i - N + 1;\n        for (let k = 0; k < N; k++) window[k] = digits[base + k];\n        const r = rank(window, factorial);\n        if (seen[r] === 0) seen[r] = 1;\n      }\n    }\n  }\n\n  for (let r = 0; r < FACT; r++) {\n    if (seen[r] === 0) {\n      return {\n        ok: false,\n        score: null,\n        gates: [gate('covers-all-permutations', false, `missing at least one permutation (rank ${r} of ${FACT} not found)`)],\n        behavior: { length: L },\n        logs: [`length=${L} missing=rank${r}`],\n      };\n    }\n  }\n\n  const gates = [\n    gate('covers-all-permutations', true, `all ${FACT} permutations of 1..${N} appear as contiguous substrings`),\n  ];\n  return {\n    ok: true,\n    score: L,\n    gates,\n    behavior: { length: L },\n    logs: [`length=${L} permutations=${FACT}`],\n  };\n}\n"}