{"id":20256267,"url":"https://github.com/devcybiko/sudoku-solver","last_synced_at":"2025-10-07T21:09:40.100Z","repository":{"id":99128368,"uuid":"402289942","full_name":"devcybiko/sudoku-solver","owner":"devcybiko","description":null,"archived":false,"fork":false,"pushed_at":"2023-01-19T15:24:04.000Z","size":41,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-11T19:00:59.930Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devcybiko.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-02T04:32:57.000Z","updated_at":"2023-01-19T15:08:07.000Z","dependencies_parsed_at":"2023-06-03T23:30:09.597Z","dependency_job_id":null,"html_url":"https://github.com/devcybiko/sudoku-solver","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/devcybiko/sudoku-solver","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devcybiko%2Fsudoku-solver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devcybiko%2Fsudoku-solver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devcybiko%2Fsudoku-solver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devcybiko%2Fsudoku-solver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devcybiko","download_url":"https://codeload.github.com/devcybiko/sudoku-solver/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devcybiko%2Fsudoku-solver/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278847409,"owners_count":26056300,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-07T02:00:06.786Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T10:46:01.877Z","updated_at":"2025-10-07T21:09:40.040Z","avatar_url":"https://github.com/devcybiko.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sudoku-solver\n\nThis is a quick hack to solve Sudoku puzzles. It uses a recursive descent / depth-first algorithm to exhaust all possible candidates.\n\nEach cell is visited and analyzed for possible candidates (looking horizontally, vertically, and in the subgrid to select digits that are not already represented).\n\nThe first candidate is added to the puzzle and the next cell is visited (working left to right, from top to bottom). That cell also selects a list of candidates and tries its first one, and calls the next cell, recursively.\n\nIf we get to a place in the recursion where no candidates exist, or if a \"child\" cell returns a 'False', a False is returned and the \"parent\" (or previous) cell - which tries its next candidate.\n\nIf a cell exhausts all its possible candidates, then it returns False to the parent which tries its next candidate and the process repeats.\n\nIf the last cell is visited and it successfully places one of its candidates, the puzzle is considered 'solved' and a True is passed up to the parents, unwinding the recursion. The algorithm then halts. If other solutions are possible, this algorithm will not find them.\n\n**NOTE** The recursive code to solve the puzzle is in `sudoku1.py`. It rightly might belong in the `Puzzle.py` class. However, I wanted to isolate the solution code in its own file. Also, I am thinking of writing a non-recursive version and putting it in a separate source file.\n\n## Installing\n* `make install`\n\n## Running unit tests / code coverage\n* `make coverage` - run all tests and code coverage\n* `make report` - generate HTML report on coverage\n\n## Run it\n* `./sudoku1.py \u003cfilename\u003e`\n\nor\n\n* `run-all.sh`\n\n## Sample puzzles were from this link - some are very hard\n* https://www.rd.com/list/printable-sudoku-puzzles/\n\n## Input file format\nThe input file is a JSON array of strings. Empty cells are represented by a single dash. Each line should have exactly 9 characters, and the array should be exactly 9 lines long.\n\n```json\n[\n    \"-7--2--46\",\n    \"-6----89-\",\n    \"2--8--715\",\n    \"-84-97---\",\n    \"71-----59\",\n    \"---13-48-\",\n    \"697--2--8\",\n    \"-58----6-\",\n    \"43--8--7-\"\n]\n\n```\n## Files\n* Makefile - makefile\n* Puzzle.py - Puzzle class (holds puzzle and its methods)\n* README.md - this file\n* puzzle-*.json - puzzle files\n* requirements.txt - required Python libraries\n* run-all.sh - script to run all puzzles\n* solved-01.json - a solved puzzle for unit tests\n* sudoku1.py - main code\n* tests/ - test cases\n\n## Implementation notes\n1. In `Puzzle.get_candiates()` I return a single candidate if the cell is already occupied. While this introduces some inefficiencies, it greatly simplified the recursion\n\n2. This is not necessarily a very efficient solution. I opted for clarity in the code over more optimal methods. For example, I could have iterated over every cell and computed the candidates (`Puzzle.get_candidates()`) once at the very beginning (rather than during the recursion) and reused them.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevcybiko%2Fsudoku-solver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevcybiko%2Fsudoku-solver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevcybiko%2Fsudoku-solver/lists"}