Repository navigation
Conversation
…ug DP The checker counted loop solutions with a plain backtracking search over the 312 grid edges (static edge order, local propagation only) and stopped early only after finding six solutions. Its cost grows exponentially with how weakly the clues constrain the board, and weak clues (many 1s and 2s) are exactly what the task rewards. On such boards it neither found six solutions nor exhausted the space within the judge's 10 s checker limit, so the checker was killed and the case scored 0. Replace the search with a plug (profile) DP over the 13 x 13 grid points. The profile holds the vertical edges crossing the sweep line as a bracket sequence of path ends, one top-edge bit per column for clue cells whose bottom edge is still open, and a flag for "loop already closed". It counts edge sets forming exactly one non-empty loop that satisfies every clue, saturating at six, so the count is exact and does not depend on how weakly the board is constrained. States live in a small open-addressing map that packs the count into each entry. Input validation, the scoring formula and the verdict message are unchanged. The checker no longer prints solution grids to stderr; the judge reads only the Ratio: line. Verified: no mismatches against brute force on small grids (2.29M instances, every 3x3 clue grid included), against the old checker on 367 boards it finishes, or against an independent SAT counter on 2,434 comparisons covering every bucket from 0 to six or more. The hardest board found (all 2s with one 3) takes about 1.2 s and 70 MB. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #182.
Problem
algorithmic/problems/145/checker.cppcounted loop solutions with a plain backtracking search over the 312 grid edges. It used a static edge order and only local propagation, and it stopped early only after findingLIMIT = 6solutions. Its cost grows exponentially as the clues get weaker, and weak clues (mostly1s and2s) are exactly what the task rewards. On such boards the search neither finds six solutions nor exhausts the space within the checker limit (10 s CPU / 20 s wall,judge_engine.js). The checker is killed and the case scores 0 with an empty message.The file header said the checker "fully reproduces behavior of the original Python+Z3 checker", but the SAT solver had been replaced by this search.
Changes
This is option 1 from the issue (proper fix). It adds no node budget and needs no statement change.
checker.cpp: replace the counter with a plug (profile) DP over the 13 × 13 grid points in row-major order. Each point decides its right and down edge. The profile has three parts:Each clue is checked when its cell's last edge is decided, and a state is pruned as soon as a cell's partial count rules it out. Counts saturate at six, so the result is exactly
min(6, number of single loops satisfying every clue), the quantity the statement scores. The run time depends on the board size, not on how constrained the board is.States are kept in a small open-addressing map that packs the count into each 8-byte entry. A hard board reaches about 0.9M states per step, too many for
unordered_mapto be fast.Unchanged: input validation (
readSol, allowed digits per mode, template positions), the scoring formula and the verdict message.The checker no longer prints up to six solution grids to stderr before the verdict. The judge only reads the
Ratio:line, so this has no effect on scoring.Verification
Built with
g++ -O2 -pipe -std=gnu++17(also at-O0;-Wall -Wextrareports nothing in the checker code) againstalgorithmic/judge/include/testlib.h. Timings below are on an Apple M3 Pro.testdata/1.ans(bundled reference)121/2boardsCorrectness, checked three independent ways:
Worst case: the hardest board a local search found (677 boards evaluated) is every clue
2with one3. It peaks at 869k states (29.7M state visits) and uses about 1.2 s CPU and 70 MB, against the 10 s / 256 MB checker limits.Archived agent runs, rebuilt from their trajectories and re-judged:
275DALt, submissions 1–2hAXcKs4, submissions 1 and 3FsXTUy2, all 3 submissionsEvery other recorded score in these trials is reproduced exactly, except seven
judge engine errorsubmissions in275DALt. Those are unrelated to this bug: the old checker finishes their boards in 0.1–1.1 s.FsXTUy2is the selected trial for problem 145 inresults/agent_scores/, so its published 0.0 comes from this bug.🤖 Generated with Claude Code