{"abstract":"A three-number run is emitted as a pair and a singleton.","category":"Phone number formatting","checks":8,"contract":"Input a list of digit strings. Deduplicate and sort by (length, text). Consecutive numbers of equal length (each one greater than the previous) form a run. A run of one is emitted as is; a longer run is emitted as START-TAIL where TAIL is END without the prefix it shares with START.","evaluation_group":"w2-phone-number-formatting-range-compress","failed_approach":"Tolerating a gap of one merges numbers that are not consecutive.","family":"w2-phone-number-formatting-range-compress-run-successor","id":"FA-96746","implementations":{"attempt":{"sha256":"fc5fad0881d2487fe067d407de64d4ea3bc94127ad52fb5fa57b5fd6833bb391","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    nums = sorted(set(x), key=lambda v: (len(v), v))\n    out = []\n    i = 0\n    while i < len(nums):\n        j = i\n        while j + 1 < len(nums) and int(nums[j + 1]) <= int(nums[j]) + 2 and len(nums[j + 1]) == len(nums[i]):\n            j += 1\n        a, b = nums[i], nums[j]\n        if a == b:\n            out.append(a)\n        else:\n            k = 0\n            while a[k] == b[k]:\n                k += 1\n            out.append(a + '-' + b[k:])\n        i = j + 1\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['run and singleton', ['5550110', '5550111', '5550112', '5550160'], ['5550110-2', '5550160']], ['duplicates inside a run', ['5550115', '5550115', '5550116'], ['5550115-6']], ['unsorted input', ['5550112', '5550110', '5550111'], ['5550110-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550130', '5550132'], ['5550130', '5550132']]], [['run and singleton', ['5550120', '5550121', '5550122', '5550170'], ['5550120-2', '5550170']], ['duplicates inside a run', ['5550125', '5550125', '5550126'], ['5550125-6']], ['unsorted input', ['5550122', '5550120', '5550121'], ['5550120-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550140', '5550142'], ['5550140', '5550142']]], [['run and singleton', ['5550130', '5550131', '5550132', '5550180'], ['5550130-2', '5550180']], ['duplicates inside a run', ['5550135', '5550135', '5550136'], ['5550135-6']], ['unsorted input', ['5550132', '5550130', '5550131'], ['5550130-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550150', '5550152'], ['5550150', '5550152']]], [['run and singleton', ['5550140', '5550141', '5550142', '5550190'], ['5550140-2', '5550190']], ['duplicates inside a run', ['5550145', '5550145', '5550146'], ['5550145-6']], ['unsorted input', ['5550142', '5550140', '5550141'], ['5550140-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550160', '5550162'], ['5550160', '5550162']]], [['run and singleton', ['5550150', '5550151', '5550152', '5550200'], ['5550150-2', '5550200']], ['duplicates inside a run', ['5550155', '5550155', '5550156'], ['5550155-6']], ['unsorted input', ['5550152', '5550150', '5550151'], ['5550150-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550170', '5550172'], ['5550170', '5550172']]]]\nfor label, arg, expected in fixtures[N - 1]:\n    check(label, solve(arg), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"cbc685b3df233f6e6456c197599babad5e952ee1a434e72a8f7824f960e41f9c","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    nums = sorted(set(x), key=lambda v: (len(v), v))\n    out = []\n    i = 0\n    while i < len(nums):\n        j = i\n        while j + 1 < len(nums) and int(nums[j + 1]) == int(nums[i]) + 1 and len(nums[j + 1]) == len(nums[i]):\n            j += 1\n        a, b = nums[i], nums[j]\n        if a == b:\n            out.append(a)\n        else:\n            k = 0\n            while a[k] == b[k]:\n                k += 1\n            out.append(a + '-' + b[k:])\n        i = j + 1\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['run and singleton', ['5550110', '5550111', '5550112', '5550160'], ['5550110-2', '5550160']], ['duplicates inside a run', ['5550115', '5550115', '5550116'], ['5550115-6']], ['unsorted input', ['5550112', '5550110', '5550111'], ['5550110-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550130', '5550132'], ['5550130', '5550132']]], [['run and singleton', ['5550120', '5550121', '5550122', '5550170'], ['5550120-2', '5550170']], ['duplicates inside a run', ['5550125', '5550125', '5550126'], ['5550125-6']], ['unsorted input', ['5550122', '5550120', '5550121'], ['5550120-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550140', '5550142'], ['5550140', '5550142']]], [['run and singleton', ['5550130', '5550131', '5550132', '5550180'], ['5550130-2', '5550180']], ['duplicates inside a run', ['5550135', '5550135', '5550136'], ['5550135-6']], ['unsorted input', ['5550132', '5550130', '5550131'], ['5550130-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550150', '5550152'], ['5550150', '5550152']]], [['run and singleton', ['5550140', '5550141', '5550142', '5550190'], ['5550140-2', '5550190']], ['duplicates inside a run', ['5550145', '5550145', '5550146'], ['5550145-6']], ['unsorted input', ['5550142', '5550140', '5550141'], ['5550140-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550160', '5550162'], ['5550160', '5550162']]], [['run and singleton', ['5550150', '5550151', '5550152', '5550200'], ['5550150-2', '5550200']], ['duplicates inside a run', ['5550155', '5550155', '5550156'], ['5550155-6']], ['unsorted input', ['5550152', '5550150', '5550151'], ['5550150-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550170', '5550172'], ['5550170', '5550172']]]]\nfor label, arg, expected in fixtures[N - 1]:\n    check(label, solve(arg), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"7718be816344333c3799284f36a47556ec1529b37d765452bd619981c869c99a","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    nums = sorted(set(x), key=lambda v: (len(v), v))\n    out = []\n    i = 0\n    while i < len(nums):\n        j = i\n        while j + 1 < len(nums) and int(nums[j + 1]) == int(nums[j]) + 1 and len(nums[j + 1]) == len(nums[i]):\n            j += 1\n        a, b = nums[i], nums[j]\n        if a == b:\n            out.append(a)\n        else:\n            k = 0\n            while a[k] == b[k]:\n                k += 1\n            out.append(a + '-' + b[k:])\n        i = j + 1\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['run and singleton', ['5550110', '5550111', '5550112', '5550160'], ['5550110-2', '5550160']], ['duplicates inside a run', ['5550115', '5550115', '5550116'], ['5550115-6']], ['unsorted input', ['5550112', '5550110', '5550111'], ['5550110-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550130', '5550132'], ['5550130', '5550132']]], [['run and singleton', ['5550120', '5550121', '5550122', '5550170'], ['5550120-2', '5550170']], ['duplicates inside a run', ['5550125', '5550125', '5550126'], ['5550125-6']], ['unsorted input', ['5550122', '5550120', '5550121'], ['5550120-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550140', '5550142'], ['5550140', '5550142']]], [['run and singleton', ['5550130', '5550131', '5550132', '5550180'], ['5550130-2', '5550180']], ['duplicates inside a run', ['5550135', '5550135', '5550136'], ['5550135-6']], ['unsorted input', ['5550132', '5550130', '5550131'], ['5550130-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550150', '5550152'], ['5550150', '5550152']]], [['run and singleton', ['5550140', '5550141', '5550142', '5550190'], ['5550140-2', '5550190']], ['duplicates inside a run', ['5550145', '5550145', '5550146'], ['5550145-6']], ['unsorted input', ['5550142', '5550140', '5550141'], ['5550140-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550160', '5550162'], ['5550160', '5550162']]], [['run and singleton', ['5550150', '5550151', '5550152', '5550200'], ['5550150-2', '5550200']], ['duplicates inside a run', ['5550155', '5550155', '5550156'], ['5550155-6']], ['unsorted input', ['5550152', '5550150', '5550151'], ['5550150-2']], ['run crossing a hundred', ['5550198', '5550199', '5550200', '5550201'], ['5550198-201']], ['different lengths do not join', ['98', '99', '100', '101'], ['98-9', '100-1']], ['run crossing a thousand', ['1998', '1999', '2000'], ['1998-2000']], ['shorter number sorts first', ['0050', '100'], ['100', '0050']], ['gap of two', ['5550170', '5550172'], ['5550170', '5550172']]]]\nfor label, arg, expected in fixtures[N - 1]:\n    check(label, solve(arg), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"A deterministic toy contract over synthetic, obviously fictitious telephone numbers and toy country tables. The rules are stipulated for this model only and make no claim of conformance with any numbering plan or telecommunications standard. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-phone-number-formatting-range-compress-run-successor","generated_at":"2026-09-29T14:52:25.575583+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Number inventories are displayed and exported as compressed ranges; a wrong run boundary or tail misstates which numbers are owned.","repair":"Compare each candidate with the previous number in the run.","root_cause":"Each candidate is compared with the run start instead of the previous number.","sha256":"b130af904073a19147715eb8eb67bb89804f79026ec91e4105894907a3c4fc2f","title":"Number list range compression: runs are compared with their start · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":38.512,"exit_code":1,"observations":[{"actual":["5550110-2","5550160"],"check":"run and singleton","expected":["5550110-2","5550160"],"passed":true},{"actual":["5550115-6"],"check":"duplicates inside a run","expected":["5550115-6"],"passed":true},{"actual":["5550110-2"],"check":"unsorted input","expected":["5550110-2"],"passed":true},{"actual":["5550198-201"],"check":"run crossing a hundred","expected":["5550198-201"],"passed":true},{"actual":["98-9","100-1"],"check":"different lengths do not join","expected":["98-9","100-1"],"passed":true},{"actual":["1998-2000"],"check":"run crossing a thousand","expected":["1998-2000"],"passed":true},{"actual":["100","0050"],"check":"shorter number sorts first","expected":["100","0050"],"passed":true},{"actual":["5550130-2"],"check":"gap of two","expected":["5550130","5550132"],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"run and singleton\", \"actual\": [\"5550110-2\", \"5550160\"], \"expected\": [\"5550110-2\", \"5550160\"], \"passed\": true}, {\"check\": \"duplicates inside a run\", \"actual\": [\"5550115-6\"], \"expected\": [\"5550115-6\"], \"passed\": true}, {\"check\": \"unsorted input\", \"actual\": [\"5550110-2\"], \"expected\": [\"5550110-2\"], \"passed\": true}, {\"check\": \"run crossing a hundred\", \"actual\": [\"5550198-201\"], \"expected\": [\"5550198-201\"], \"passed\": true}, {\"check\": \"different lengths do not join\", \"actual\": [\"98-9\", \"100-1\"], \"expected\": [\"98-9\", \"100-1\"], \"passed\": true}, {\"check\": \"run crossing a thousand\", \"actual\": [\"1998-2000\"], \"expected\": [\"1998-2000\"], \"passed\": true}, {\"check\": \"shorter number sorts first\", \"actual\": [\"100\", \"0050\"], \"expected\": [\"100\", \"0050\"], \"passed\": true}, {\"check\": \"gap of two\", \"actual\": [\"5550130-2\"], \"expected\": [\"5550130\", \"5550132\"], \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":38.675,"exit_code":1,"observations":[{"actual":["5550110-1","5550112","5550160"],"check":"run and singleton","expected":["5550110-2","5550160"],"passed":false},{"actual":["5550115-6"],"check":"duplicates inside a run","expected":["5550115-6"],"passed":true},{"actual":["5550110-1","5550112"],"check":"unsorted input","expected":["5550110-2"],"passed":false},{"actual":["5550198-9","5550200-1"],"check":"run crossing a hundred","expected":["5550198-201"],"passed":false},{"actual":["98-9","100-1"],"check":"different lengths do not join","expected":["98-9","100-1"],"passed":true},{"actual":["1998-9","2000"],"check":"run crossing a thousand","expected":["1998-2000"],"passed":false},{"actual":["100","0050"],"check":"shorter number sorts first","expected":["100","0050"],"passed":true},{"actual":["5550130","5550132"],"check":"gap of two","expected":["5550130","5550132"],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"run and singleton\", \"actual\": [\"5550110-1\", \"5550112\", \"5550160\"], \"expected\": [\"5550110-2\", \"5550160\"], \"passed\": false}, {\"check\": \"duplicates inside a run\", \"actual\": [\"5550115-6\"], \"expected\": [\"5550115-6\"], \"passed\": true}, {\"check\": \"unsorted input\", \"actual\": [\"5550110-1\", \"5550112\"], \"expected\": [\"5550110-2\"], \"passed\": false}, {\"check\": \"run crossing a hundred\", \"actual\": [\"5550198-9\", \"5550200-1\"], \"expected\": [\"5550198-201\"], \"passed\": false}, {\"check\": \"different lengths do not join\", \"actual\": [\"98-9\", \"100-1\"], \"expected\": [\"98-9\", \"100-1\"], \"passed\": true}, {\"check\": \"run crossing a thousand\", \"actual\": [\"1998-9\", \"2000\"], \"expected\": [\"1998-2000\"], \"passed\": false}, {\"check\": \"shorter number sorts first\", \"actual\": [\"100\", \"0050\"], \"expected\": [\"100\", \"0050\"], \"passed\": true}, {\"check\": \"gap of two\", \"actual\": [\"5550130\", \"5550132\"], \"expected\": [\"5550130\", \"5550132\"], \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":40.084,"exit_code":0,"observations":[{"actual":["5550110-2","5550160"],"check":"run and singleton","expected":["5550110-2","5550160"],"passed":true},{"actual":["5550115-6"],"check":"duplicates inside a run","expected":["5550115-6"],"passed":true},{"actual":["5550110-2"],"check":"unsorted input","expected":["5550110-2"],"passed":true},{"actual":["5550198-201"],"check":"run crossing a hundred","expected":["5550198-201"],"passed":true},{"actual":["98-9","100-1"],"check":"different lengths do not join","expected":["98-9","100-1"],"passed":true},{"actual":["1998-2000"],"check":"run crossing a thousand","expected":["1998-2000"],"passed":true},{"actual":["100","0050"],"check":"shorter number sorts first","expected":["100","0050"],"passed":true},{"actual":["5550130","5550132"],"check":"gap of two","expected":["5550130","5550132"],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"run and singleton\", \"actual\": [\"5550110-2\", \"5550160\"], \"expected\": [\"5550110-2\", \"5550160\"], \"passed\": true}, {\"check\": \"duplicates inside a run\", \"actual\": [\"5550115-6\"], \"expected\": [\"5550115-6\"], \"passed\": true}, {\"check\": \"unsorted input\", \"actual\": [\"5550110-2\"], \"expected\": [\"5550110-2\"], \"passed\": true}, {\"check\": \"run crossing a hundred\", \"actual\": [\"5550198-201\"], \"expected\": [\"5550198-201\"], \"passed\": true}, {\"check\": \"different lengths do not join\", \"actual\": [\"98-9\", \"100-1\"], \"expected\": [\"98-9\", \"100-1\"], \"passed\": true}, {\"check\": \"run crossing a thousand\", \"actual\": [\"1998-2000\"], \"expected\": [\"1998-2000\"], \"passed\": true}, {\"check\": \"shorter number sorts first\", \"actual\": [\"100\", \"0050\"], \"expected\": [\"100\", \"0050\"], \"passed\": true}, {\"check\": \"gap of two\", \"actual\": [\"5550130\", \"5550132\"], \"expected\": [\"5550130\", \"5550132\"], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}