[−][src]Module sudoku_variants::constraint
This module defines constraints which can be applied tu Sudoku grids, thus specifying the rules of the puzzle.
Besides the definition of the Constraint trait, this crate contains some predefined constraint for default Sudoku rules and some variants. We will cover them first and afterwards show how to implement a custom constraint.
Default Sudoku rules
To get the default Sudoku rules, DefaultConstraint can be used. Conceptually, it is a conjunction of RowConstraint, ColumnConstraint, and BlockConstraint.
Variants
Besides the default rules, sudoku-variants
also offers some pre-defined
variantions. As an example, we will use the
DiagonalsConstraint, which requires that
the two diagonals, top-left to bottom-right and top-right to bottom-left,
do not contain duplicate digits, just like each row, column, and block in
standard Sudoku.
Normally, one wants to apply a DiagonalsConstraint
and a
DefaultConstraint
. This can be done in two ways: using a
CompositeConstraint and using a
DynamicConstraint. The first is
type-checked over two parameter types, which both need to be constraints.
It is provided one instance of each type, and is defined to be fulfilled
if both instances are fulfilled. In contrast, the DynamicConstraint
uses
a vector of trait objects and is fulfilled if all entries are fulfilled.
This enables a more flexible design and is less cumbersome, especially when
combining more than two constraints, but comes at a runtime cost due to
dynamic dispatch.
To define our combination of default- and diagonals-constraints, we can write the following code:
use sudoku_variants::constraint::{ CompositeConstraint, DefaultConstraint, DiagonalsConstraint, DynamicConstraint }; // Option 1: CompositeConstraint let c1 = CompositeConstraint::new(DefaultConstraint, DiagonalsConstraint); // Option 2: DynamicConstraint let c2 = DynamicConstraint::with_children(vec![ Box::new(DefaultConstraint), Box::new(DiagonalsConstraint) ]);
Custom constraints
When implementing a constraint, it is usually sufficient to implement
Constraint.check_number. All
other methods are default-implemented based on it. However, the performance
of Constraint.check could be improved
by a specialized implementation, since by default it calls check_number
for every cell.
As an example of an implementation of a custom constraint, we will look at
the source code of a subset of the DiagonalsConstraint
, which we call
MainDiagonalConstraint
. It only checks the diagonal from the top-left to
the bottom-right corner of the Sudoku.
use sudoku_variants::SudokuGrid; use sudoku_variants::constraint::Constraint; #[derive(Clone)] struct MainDiagonalConstraint; impl Constraint for MainDiagonalConstraint { fn check_number(&self, grid: &SudokuGrid, column: usize, row: usize, number: usize) -> bool { // For all cells on the diagonal, the column index is equal to the // row index. All other cells don't interact with this constraint, // so we return true, indicating that they don't violate it. if column == row { let size = grid.size(); for i in 0..size { // Since column == row, if i == column we are looking at // the checked cell itself, which may contain the number. if i != column && grid.has_number(i, i, number).unwrap() { return false; } } } true } }
Deriving Clone
is important, since occasionally Sudoku need to be cloned.
Sudoku therefore implements Clone
, which requires its constraint to be
cloneable aswell. Note that Clone
is not required by the Constraint
trait, since that would make it impossible to create Constraint
-trait
objects, which are used in the DynamicConstraint
. Instead,
CloneConstraint, which clones a trait object,
is required for elements of a DynamicConstraint
. However, if you derive
Clone
, you do not need to worry about CloneConstraint
, since it is
implemented on every constraint that implements Clone
by default.
Structs
AdjacentConsecutiveConstraint | A |
BlockConstraint | A |
ColumnConstraint | A |
CompositeConstraint | A |
DefaultConstraint | The default Sudoku |
DiagonallyAdjacentConstraint | A |
DiagonalsConstraint | A |
DynamicConstraint | A |
KingsMoveConstraint | A |
KnightsMoveConstraint | A |
RowConstraint | A |
Traits
CloneConstraint | A trait for cloneable |
Constraint | A constraint defines some property on a Sudoku grid. These are essentially
the rules of the Sudoku. In standard Sudoku these are "No duplicates in a
row" ( |
RelativeCellConstraint | A trait for |