volt: Q95 -- find_duplicate gets a declared dead branch and 12 collected cells

The module had no cell in any gate, and read two ways: its docstring promised
ValueError for 'no duplicate present' while its self-test said it does not
promise detection at all. Measured at 95e4962: every array of length n+1 over
1..n for n=1..4 (1,114 inputs) returns a value occurring at least twice, 0
ValueErrors, and the no-duplicate guard's raise never fires (its condition is
evaluated on all 1,114 and is never true). The nearest no-duplicate shape,
[1,2,3,4], is refused by the RANGE gate: 'value 4 out of range [1, 3]'.

- find_duplicate.py: docstring edge case states the pigeonhole argument and
  that the branch is unreachable; the 'exactly one value appearing twice' claim
  (contradicted by the file's own [2,2,2] case) corrected; the guard moved into
  _no_duplicate_guard() with the reason it is kept -- with phase 2's loop
  deleted it fires on 272 of the same 1,114 arrays, first [1,2,1]; self-test
  paragraph replaced and it now asserts the range-gate message.
- test_find_duplicate.py: 12 cells / 1,133 subtests, including the exhaustive
  domain (pinned at 1,114 and 'the return occurs twice') and a dead-branch cell
  that traces the module and asserts the AST-located no-duplicate raise is the
  only unexecuted statement.
- Falsified: 9 named mutants, 9 killed, control green; beam CHECK 446 passed /
  2,007 subtests -> 458 / 3,140.
This commit is contained in:
Volt committed 2026-10-28 19:23:04 +00:00
1 parent 95e49625a4
commit bab4431884
2 files changed
+263 -16

No files matched your search

+47 -16
View File
@@ -1,18 +1,43 @@
"""Find the duplicate in an array of n+1 integers each in [1, n].
"""Find a duplicate in an array of n+1 integers each in [1, n].
Classic Floyd's tortoise-and-hare on the implicit linked list defined by
f(i) = nums[i]. Guarantees O(n) time, O(1) extra space, and does not
mutate the input. Returns the single duplicated value (input is assumed
to contain exactly one value appearing twice, all others once).
mutate the input. Returns a duplicated value; when several values repeat,
returns one of them (the entry point of the cycle reachable from index 0).
Edge cases handled:
- len(nums) < 2 -> ValueError
- values out of [1, n] -> ValueError
- no duplicate present -> ValueError (defensive; Floyd would loop)
- values out of [1, n], or not a plain int (bool and float included)
-> ValueError
- no duplicate present -> unreachable, and therefore never raised:
a no-duplicate array cannot satisfy both preconditions at once. With
len(nums) = n + 1 values drawn from 1..n, pigeonhole forces a repeat;
the only arrays that avoid one are shorter than n + 1 or carry a value
outside 1..n, and both are refused by the gates above before Floyd
runs (see `_no_duplicate_guard()`). The count check after phase 2 is
kept as an invariant, not as a handler: an entry node has two distinct
predecessors by definition, so its value occurs at least twice.
"""
from typing import List
def _no_duplicate_guard(candidate: int, nums: List[int]) -> int:
"""Invariant: the phase-2 entrance value is duplicated, or raise.
Unreachable on validated input (see the module docstring). It is here so
that an edit which widens the gates above -- or shortens phase 2, the other
half of the argument -- fails loudly instead of returning a value as if it
were a duplicate. Measured: the raise fires 0 times over every validated
input for n = 1..4, and it *does* fire when phase 2's loop is deleted, which
is the edit it exists for. `test_find_duplicate.py` pins that this is the
module's only unexecuted line, so removing it, or growing new dead code
beside it, moves a cell.
"""
if nums.count(candidate) < 2:
raise ValueError("no duplicate present in nums")
return candidate
def find_duplicate(nums: List[int]) -> int:
n = len(nums) - 1
if n < 1:
@@ -33,12 +58,10 @@ def find_duplicate(nums: List[int]) -> int:
while slow2 != slow:
slow2 = nums[slow2]
slow = nums[slow]
candidate = slow
# Verify the candidate actually occurs more than once; a permutation
# (no duplicate) also has cycles, so Floyd alone is not sufficient.
if nums.count(candidate) < 2:
raise ValueError("no duplicate present in nums")
return candidate
# Floyd alone would return an entrance value even for a permutation; the
# guard below states the invariant that the range gates make that
# impossible. It is a proof checkpoint, not a scenario handler.
return _no_duplicate_guard(slow, nums)
def _self_test() -> None:
@@ -81,11 +104,19 @@ def _self_test() -> None:
else:
raise AssertionError(f"expected ValueError for {bad!r}")
# No duplicate (all distinct) -> must not hang; we detect via timeout-ish
# guard: a distinct permutation of [1..n] has no cycle reachable from 0? Actually
# f on a permutation is a set of cycles; Floyd may find a cycle that is NOT a
# duplicate. We therefore do NOT promise detection of the no-duplicate case;
# instead we assert it raises OR returns something, but never hangs.
# The no-duplicate case never reaches Floyd: a permutation of 1..n has
# length n, which is one short of a valid input, so the range gate
# refuses it with an out-of-range message. The `no duplicate present`
# branch cannot fire on any validated input -- pinned as the module's
# only unexecuted line in test_find_duplicate.py.
for permutation in ([1, 2, 3, 4], [2, 1], [1, 2, 3]):
try:
find_duplicate(list(permutation))
except ValueError as exc:
assert "out of range" in str(exc), (permutation, exc)
else:
raise AssertionError(f"expected ValueError for {permutation!r}")
print("ALL TESTS PASSED")
+216
View File
@@ -0,0 +1,216 @@
"""Cells for `find_duplicate` (Q95, volt, 2026-10-28).
The module had no cell in any gate, and the record that opened Q95 measured a
`raise ValueError("no duplicate present in nums")` that no validated input can
reach. These cells do two things a green gate could not do before: they grade
the behaviour over the whole validated domain (n = 1..4, every array), and they
grade the *shape* of the code -- the no-duplicate guard is declared as the
module's only unexecuted line, so deleting it, or growing new dead code beside
it, moves a cell.
Run from the lane directory: python3 -m pytest -q test_find_duplicate.py
"""
import ast
import itertools
import sys
import unittest
from pathlib import Path
import find_duplicate as fd
MODULE_PATH = Path(fd.__file__)
def _module_source():
return MODULE_PATH.read_text(encoding="utf-8")
def _traced_call(func, *args):
"""Call func(*args), returning (result_or_exception, executed_line_set)."""
executed = set()
def local(frame, event, arg):
if event == "line" and frame.f_code.co_filename == str(MODULE_PATH):
executed.add(frame.f_lineno)
return local
previous = sys.gettrace()
sys.settrace(local)
try:
try:
result = func(*args)
except Exception as exc: # noqa: BLE001 - the caller grades the class
result = exc
finally:
sys.settrace(previous)
return result, executed
def _valid_arrays(n):
return itertools.product(range(1, n + 1), repeat=n + 1)
NO_DUPLICATE_INPUTS = ([], [1], [0, 1], [1, 3], [1, 2, 3, 4], [True, 1],
[1.0, 1], ["1", 1])
NO_DUPLICATE_PERMUTATIONS = ([1, 2, 3, 4], [2, 1], [1, 2, 3])
class KnownDuplicates(unittest.TestCase):
def test_each_documented_case_returns_its_duplicate(self):
cases = [
([1, 3, 4, 2, 2], 2),
([3, 1, 3, 4, 2], 3),
([1, 1], 1),
([2, 2, 2], 2),
([1, 2, 3, 4, 5, 5], 5),
([2, 4, 3, 2, 1], 2),
# Phase 1's meeting point is inside the cycle and its value (3)
# occurs once; only phase 2's entrance (2) is the duplicate. A
# suite whose cases all have meeting == entrance cannot see phase 2
# go missing -- this case can.
([1, 2, 3, 4, 2], 2),
]
for nums, expected in cases:
with self.subTest(nums=nums):
self.assertEqual(fd.find_duplicate(list(nums)), expected)
def test_input_is_not_mutated(self):
nums = [3, 1, 3, 4, 2]
snapshot = list(nums)
fd.find_duplicate(nums)
self.assertEqual(nums, snapshot)
def test_repeated_calls_are_deterministic(self):
nums = [4, 3, 4, 2, 1]
reads = {fd.find_duplicate(list(nums)) for _ in range(5)}
self.assertEqual(reads, {4})
class ValidatedDomain(unittest.TestCase):
def test_domain_size_is_the_pigeonhole_domain(self):
# n**(n+1) for n = 1..4 -> 1 + 8 + 81 + 1024
self.assertEqual(sum(n ** (n + 1) for n in range(1, 5)), 1114)
def test_every_validated_array_returns_a_value_occurring_twice(self):
total = 0
for n in range(1, 5):
for array in _valid_arrays(n):
total += 1
nums = list(array)
with self.subTest(nums=nums):
got = fd.find_duplicate(nums)
self.assertGreaterEqual(nums.count(got), 2)
def test_no_validated_array_raises_anything(self):
total = raises = 0
for n in range(1, 5):
for array in _valid_arrays(n):
total += 1
try:
fd.find_duplicate(list(array))
except Exception as exc: # noqa: BLE001 - any raise is the finding
raises += 1
self.fail("validated input raised %r: %r" % (array, exc))
self.assertEqual((total, raises), (1114, 0))
class RefusedInputs(unittest.TestCase):
def test_short_arrays_are_refused_by_the_length_gate(self):
for bad in ([], [1]):
with self.subTest(bad=bad):
with self.assertRaises(ValueError) as ctx:
fd.find_duplicate(list(bad))
self.assertIn("at least 2 elements", str(ctx.exception))
def test_out_of_range_values_are_refused_by_the_range_gate(self):
for bad in ([0, 1], [1, 3], [1, 2, 3, 4], [-1, 1]):
with self.subTest(bad=bad):
with self.assertRaises(ValueError) as ctx:
fd.find_duplicate(list(bad))
self.assertIn("out of range", str(ctx.exception))
def test_bools_floats_and_strings_are_not_ints_for_this_contract(self):
for bad in ([True, 1], [1.0, 1], ["1", 1]):
with self.subTest(bad=bad):
with self.assertRaises(ValueError) as ctx:
fd.find_duplicate(list(bad))
self.assertIn("out of range", str(ctx.exception))
def test_no_duplicate_shape_is_refused_by_the_range_gate_not_by_floyd(self):
# Q95's reading: a no-duplicate array of length n+1 over 1..n cannot
# exist, so the nearest no-duplicate shape is one short and dies on the
# range gate -- never on the "no duplicate present" branch.
for permutation in NO_DUPLICATE_PERMUTATIONS:
with self.subTest(permutation=permutation):
with self.assertRaises(ValueError) as ctx:
fd.find_duplicate(list(permutation))
message = str(ctx.exception)
self.assertIn("out of range", message)
self.assertNotIn("no duplicate present", message)
class DeadBranchIsDeclared(unittest.TestCase):
"""The no-duplicate guard is the module's only unexecuted line."""
def _guard_raise_lineno(self):
tree = ast.parse(_module_source())
for node in ast.walk(tree):
if isinstance(node, ast.Raise) and isinstance(node.exc, ast.Call):
for arg in node.exc.args:
if isinstance(arg, ast.Constant) and isinstance(arg.value, str):
if "no duplicate present" in arg.value:
return node.lineno
self.fail("the no-duplicate raise is gone from find_duplicate.py")
def _statement_lines(self):
tree = ast.parse(_module_source())
def is_docstring(node):
return (
isinstance(node, ast.Expr)
and isinstance(node.value, ast.Constant)
and isinstance(node.value.value, str)
)
lines = set()
for node in tree.body:
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
if node.name == "_self_test":
continue # its own asserts are not this module's behaviour
# `def` itself emits no line event, and a docstring is an
# Expr the interpreter never steps into.
for inner in ast.walk(node):
if isinstance(inner, ast.stmt) and not is_docstring(inner):
lines.add(inner.lineno)
lines.discard(node.lineno)
return lines
def test_only_the_no_duplicate_raise_is_unexecuted(self):
executed = set()
for n in range(1, 5):
for array in _valid_arrays(n):
_, seen = _traced_call(fd.find_duplicate, list(array))
executed |= seen
for bad in NO_DUPLICATE_INPUTS + NO_DUPLICATE_PERMUTATIONS:
_, seen = _traced_call(fd.find_duplicate, list(bad))
executed |= seen
declared_dead = self._guard_raise_lineno()
unexecuted = self._statement_lines() - executed
self.assertEqual(
unexecuted, {declared_dead},
"unexecuted lines (declared dead line %d): %s"
% (declared_dead, sorted(unexecuted)),
)
def test_the_guard_cannot_fire_on_validated_input(self):
# Independent of line numbers: no validated call may produce the
# "no duplicate present" message.
for n in range(1, 5):
for array in _valid_arrays(n):
result, _ = _traced_call(fd.find_duplicate, list(array))
self.assertNotIsInstance(result, ValueError, array)
if __name__ == "__main__":
unittest.main()