Skip to main content

Other formats

The sudoku-puzzle format (Puzzle format) is all a tool needs. pencilmark can also read and write a few other formats for convenience. None of them is part of the format or required by it.

FunctionReadsWrites
from_string(s) / to_string(puzzle, "plain")plain classic strings, also with a trailing commentplain classic strings
from_string(s) / to_string(puzzle, "grid")text grids with |, -, + separators (Simple Sudoku, forums)text grids
from_string(s)pencil-mark grids, 729-character candidate strings–
from_string(s) / to_string(puzzle, "sudokuwiki")sudokuwiki.org packed stringssudokuwiki.org packed strings
from_ipuz(ipuz) / to_ipuz(puzzle)ipuz 1 and 2 sudokuipuz 2
pencilmark.sources.load(url)f-puzzles, SudokuPad (SCL / fpuz / ctc), Penpa+, Logic Masters links–

from_string returns a sudoku-puzzle dict. sources.load returns pencilmark's internal puzzle JSON; to_export turns it into a sudoku-puzzle file. Every entry point (rate, solve, load, describe, the command line) also accepts these strings and links directly.

Plain classic string​

  • D×D characters in reading order; whitespace and line breaks are ignored.
  • Empty cell: ., 0, - or _. Digits 1–9, then A–Z for 10–35 (case-insensitive).
  • D = √length for D in {4, 6, 8, 9, 10, 12, 14, 15, 16, 20, 25}; boxes are the standard shape (4: 2×2, 6: 2 rows × 3 columns, 8: 2×4, 9: 3×3, 10: 2×5, 12: 3×4, 14: 2×7, 15: 3×5, 16: 4×4, 20: 4×5, 25: 5×5).
  • to_string(…, "plain") writes . for empty cells and refuses anything but a classic with standard boxes and no other rules.

Text grids​

The same classic puzzle laid out on lines, as Simple Sudoku (.ss), SadMan (.sdk) and forum posts write it:

. . . | . 4 . | 8 . 3 *-----------*
. 6 . | . . 8 | . . 2 |...|.4.|8.3|
9 . 8 | 6 . 5 | . . 1 |.6.|..8|..2|
------+-------+------ |9.8|6.5|..1|
2 3 5 | . . . | . . . |---+---+---|
… …
  • Lines made only of -, +, =, |, * and spaces, with at least one -, + or =, are separators and skipped; | and spaces inside a row are ignored; * is also an empty cell.
  • Text after # or ; on a line is a comment (<81 characters> # rating 5.9).
  • to_string(…, "grid") writes the left-hand form (refuses what a plain string cannot carry).

Pencil marks​

  • Pencil-mark grid: one whitespace-separated token per cell in reading order (separators as above). A token with one digit is a given; several digits are that cell's candidates (candidates in the puzzle).
  • 729-character candidate string (Sukaku): 9 characters per cell, position k holds the digit k+1 when it is a candidate and . or 0 otherwise; a cell with a single candidate is a given.
  • HoDoKu library line (:0901:4:<81 characters>:<removed candidates>:…): the puzzle and its removed candidates (tokens drc = digit d is not a candidate of rRcC); the fields describing the collected step are ignored.

These are read only. A multi-line grid is one puzzle: pass it to from_string / rate as one string (the command line reads one puzzle per line).

sudokuwiki.org packed strings​

These are the puzzle strings used by the solvers on sudokuwiki.org, Andrew Stuart's site. They are described on his Sudoku String Definitions page; the full encoding reference is the puzzle-coding documentation by Quintin May (source). A string is a 3-character header (puzzle type, size, encoding version) followed by one base-36 value per cell.

pencilmark reads and writes these headers:

HeaderPuzzleRead as
S9B, S6Bclassic 9×9, 6×6one box_grid
X9BSudoku X+ both main diagonals (region kind diagonal)
W9BWindoku+ the 4 windows (region kind window)
C9BColour Sudoku+ 9 groups at the same position in every box (region kind disjoint)
J9BJigsawbox rules
L9B, L6CKiller 9×9, 6×6+ cage rules (L6C: + cages only)
M9BKiller Jigsawbox and cage rules

Anything else (other puzzle types or versions, placed digits or candidates, 6×6 killer operators other than +) is refused when read. to_string(puzzle, "sudokuwiki") picks the header from the structure and refuses puzzles none of these headers can express (a 6×6 jigsaw or X, killer-X, killer-windoku, anything above 9×9).

ipuz​

to_ipuz(puzzle) writes ipuz 2 (sudoku kinds) for the subset that maps cleanly and refuses the rest:

pencilmarkipuz
one box_grid of the standard box shapekind http://ipuz.org/sudoku#1, boxes: true
one grid, no boxes (Latin square)http://ipuz.org/sudoku/latinsquare#1, boxes: false
+ both main diagonalshttp://ipuz.org/sudoku/diagonalsudoku#1, zones
+ region windowhttp://ipuz.org/sudoku/hypersudoku#1, zones with rect
one grid + box rules (jigsaw)http://ipuz.org/sudoku/jigsawsudoku#1, boxes: false, one zone per box
+ cagehttp://ipuz.org/sudoku/killersudoku#1, cages (value), showoperators: false, cageborder: "dashed"

puzzle and solution are row arrays (0 = empty); ipuz coordinates are [col, row], 1-based. meta title / author / url / id / date map to title, author, url, uniqueid, date (mm/dd/yyyy). The complete pencilmark object goes in "io.github.silly-puppyy.pencilmark:puzzle", with "volatile": {"io.github.silly-puppyy.pencilmark": "puzzle,solution,zones,cages"}. Given candidates (Sukaku) are refused: ipuz has no field for them.

from_ipuz(ipuz) (a dict or JSON text) reads the same subset back: puzzle and solution (numbers, digit strings or {"cell": …} objects; empty as declared), boxes, zones (on a jigsaw, zones of D cells are its boxes; both main diagonals become region kind diagonal, rect zones window, any other zone region) and cages with a value. A file written by to_ipuz returns its embedded puzzle as long as the grid was not edited. Other kinds, omitted or block cells, and cages without a sum are refused.

Site loaders​

pencilmark.sources reads f-puzzles, SudokuPad (SCL / fpuz / ctc), Penpa+ and Logic Masters links, and to_export turns the result into a sudoku-puzzle file. Writing those formats is not supported. Loaders that fetch pages identify themselves, obey robots.txt and pause between requests.