This is a Tampermonkey script for sudoku setters. It allows you to take a SudokuMaker puzzle and automatically convert it into an Interactive Sudoku Solver (ISS) puzzle.
ISS is one of the fastest engines to solve variant sudokus and runs completely in the browser. The primary use case of this extension is to have an easy and fast way to check the validity and uniqueness of puzzles while typesetting those puzzles in SudokuMaker.
Note: I am not the developer of either of those two powerful web applications but only wrote some logic that allows you to combine their powers easily.
The user script needs Tampermonkey. After you installed Tampermonkey, install the Sudokumaker ISS Export user script. Now you can perform an automatic export in SudokuMaker with "Ctrl+I". The automatic export will open a new tab with the ISS version of the puzzle. Alternatively, Ctrl+Alt+I will generate an ISS version of the puzzle that treats all blue digits as givens and all centermarks as "given centermarks".
Almost all constraints (excl. custom constraints, see below) in SudokuMaker are automatically converted into equivalent ISS constraints during the export. This includes:
There are certain cases where an automatic conversion is not possible at the moment.
Custom constraints can add an issExport() function in their implementation.
If this function is provided, the export will take the custom constraint into account when generating the ISS version of a puzzle.
If no such function is provided, the custom constraint will be ignored by the export.
To get started with custom iss exports, visit the demo page which showcases some constraints and links to SudokuMaker projects and the LMD source of the demo puzzles. You can use the copy icon in the demo page to import the constraints into your puzzles.
issExport() takes two arguments: input and api.
input is the same as usual in custom constraints and only relevant for local constraints.
The functions in api can be used to add new constraints to the ISS puzzle.
The function will be called once for every export.
The simplest example is to add a global constraint that is already available in ISS, such as dutch flat mates.
function issExport(input, api) {
api.addGlobalConstraint("DutchFlatmates")
}
Some line constraints are implemented in ISS but not in SudokuMaker.
Those can easily be added via the addLines() helper function.
Make sure to disable the "global constraint" checkbox and add the groups.
function issExport(input, api) {
api.addLine("Zipper", input.groups)
}
addLines() accepts a third argument value which is sometimes needed. For example, to create a lockout line with a minumm difference of 6, the following can be used.
function issExport(input, api) {
api.addLine("Lockout", input.groups, 6)
}
The value argment can also be used to forward the values of the groups via a function.
function issExport(input, api) {
api.addLine("RellikCage", input.groups, group => group.value)
}
To define a pair constraint for the export, use addPairConstraintT().
Just like addLine() the second argument (groups) defines the line shapes and
the first argument is a name for the constraint. However, the name here is purely descriptive, and no rules
will be inferred from it.
The third argument check is a function that checks whether adjacent digits along a line are valid neighbors.
function issExport({groups}, {addPairConstraint}) {
addPairConstraint("Slow Thermo", groups, (a, b) => a <= b);
}
There is also a fourth argument allPairs which can be used to specify whether all pairs on the line — not just adjacent ones — have to pass the check.
function issExport({groups}, {addPairConstraint}) {
const check = (a, b) => Math.abs(a - b) > 1;
const allPairs = true;
addPairConstraint("Nabner", groups, check, allPairs);
}
With "Regex lines", you can define a regular expression pattern that must be satisfied by the digits along a line. The following example implements a "flatmate line". At least one 5 must be on the line with a 1 before it and/or a 9 after it. The third argument can be a string or a reglar expression.
function issExport({groups}, {addRegexLine}) {
addRegexLine("Flatmate Line", groups, /.*(15|59).*/)
}
State machines are the most flexible type of custom constraint in ISS.
You can learn more about state machines in the ISS documentation or on Wikipedia.
State machines can be added with addStateMachine().
The first two arguments are similar to addPairConstraint().
The third argument is an object that defines the state machine.
function issExport({groups}, {addStateMachine}) {
addStateMachine("Cells sum to less than 10", groups, {
startState: 0,
transition: (state, value) => (state + value < 10) ? state + value: [],
accept: state => state < 10,
maxDepth: 10 // maxDepth is optional and not needed here
})
}
The state machine starts at the specified startState. In case of non-branching state machines,
the values of the cells are passed to transition() one at a time until there are no more cells left or until transition() signals that the line is already broken.
For non-branching state machines, the line is invalid if transition() returns nothing (or en empty array) at any point or if the final state (the state after every value was passed to transition()) does not pass accept().
let state = machine.startState
for (const value of lineValues) {
state = machine.transition(state, value)
if (state == undefined || state == []) { return "bad values" }
}
return machine.accept(state) ? "good values" : "bad values"
transition() can return an array of states.
If it does, at least one of the states must find a way to transition into an accepted state.
Branching can occur multiple times througout the transitions.
This is known as a non-deterministic state machine.
function issExport({groups}, {addStateMachine}) {
addStateMachine("Cells sum to 20 or 30", groups, {
startState: null,
transition: (state, value) => {
if (state == null) return [20 - value, 30 - value]
return value > state ? [] : state - value;
},
accept: state => state == 0
})
}