Add a hidden single strategy.
This commit is contained in:
parent
a6b35d6bf3
commit
ea1d345a4e
|
@ -1,5 +1,5 @@
|
||||||
use crate::board::Board;
|
use crate::board::Board;
|
||||||
use crate::strategy::{NakedSingle, Strategy, StrategyFn};
|
use crate::strategy::{HiddenSingle, NakedSingle, Strategy, StrategyFn};
|
||||||
use crate::validator;
|
use crate::validator;
|
||||||
|
|
||||||
fn try_strategies(strategies: &[StrategyFn], sudoku_board: &Board) -> Option<Box<dyn Strategy>> {
|
fn try_strategies(strategies: &[StrategyFn], sudoku_board: &Board) -> Option<Box<dyn Strategy>> {
|
||||||
|
@ -21,7 +21,7 @@ pub fn solve_board(mut sudoku_board: Board) -> Result<Board, Board> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let strategies: [StrategyFn; 1] = [NakedSingle::find_instance];
|
let strategies: [StrategyFn; 2] = [NakedSingle::find_instance, HiddenSingle::find_instance];
|
||||||
|
|
||||||
while let Some(ns) = try_strategies(&strategies, &sudoku_board) {
|
while let Some(ns) = try_strategies(&strategies, &sudoku_board) {
|
||||||
sudoku_board = ns.apply(sudoku_board);
|
sudoku_board = ns.apply(sudoku_board);
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
use crate::board::Board;
|
||||||
|
use crate::square::Square;
|
||||||
|
use crate::strategy::Strategy;
|
||||||
|
|
||||||
|
pub struct HiddenSingle {
|
||||||
|
index: u8,
|
||||||
|
value: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Seen {
|
||||||
|
NotSeen,
|
||||||
|
SeenOnce(u8),
|
||||||
|
SeenTwice,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Strategy for HiddenSingle {
|
||||||
|
fn find_instance(board: &Board) -> Option<Box<dyn Strategy>> {
|
||||||
|
for r in 0..9 {
|
||||||
|
for n in 1..=9 {
|
||||||
|
let seen = board
|
||||||
|
.row(r)
|
||||||
|
.fold(Seen::NotSeen, |curr, square| match square {
|
||||||
|
Square::Marks(i, opts) => {
|
||||||
|
if opts.get(n as usize) {
|
||||||
|
match curr {
|
||||||
|
Seen::NotSeen => Seen::SeenOnce(i),
|
||||||
|
_ => Seen::SeenTwice,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
curr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => curr,
|
||||||
|
});
|
||||||
|
match seen {
|
||||||
|
Seen::SeenOnce(i) => {
|
||||||
|
return Some(Box::new(HiddenSingle { index: i, value: n }))
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for c in 0..9 {
|
||||||
|
for n in 1..=9 {
|
||||||
|
let seen = board
|
||||||
|
.col(c)
|
||||||
|
.fold(Seen::NotSeen, |curr, square| match square {
|
||||||
|
Square::Marks(i, opts) => {
|
||||||
|
if opts.get(n as usize) {
|
||||||
|
match curr {
|
||||||
|
Seen::NotSeen => Seen::SeenOnce(i),
|
||||||
|
_ => Seen::SeenTwice,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
curr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => curr,
|
||||||
|
});
|
||||||
|
match seen {
|
||||||
|
Seen::SeenOnce(i) => {
|
||||||
|
return Some(Box::new(HiddenSingle { index: i, value: n }))
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for b in 0..9 {
|
||||||
|
for n in 1..=9 {
|
||||||
|
let seen = board
|
||||||
|
.boxn(b)
|
||||||
|
.fold(Seen::NotSeen, |curr, square| match square {
|
||||||
|
Square::Marks(i, opts) => {
|
||||||
|
if opts.get(n as usize) {
|
||||||
|
match curr {
|
||||||
|
Seen::NotSeen => Seen::SeenOnce(i),
|
||||||
|
_ => Seen::SeenTwice,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
curr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => curr,
|
||||||
|
});
|
||||||
|
match seen {
|
||||||
|
Seen::SeenOnce(i) => {
|
||||||
|
return Some(Box::new(HiddenSingle { index: i, value: n }))
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(&self, mut board: Board) -> Board {
|
||||||
|
board.squares[self.index as usize] = Square::Value(self.index, self.value);
|
||||||
|
board.restrict_marks();
|
||||||
|
board
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
pub mod base;
|
pub mod base;
|
||||||
|
|
||||||
|
pub mod hidden_single;
|
||||||
pub mod naked_single;
|
pub mod naked_single;
|
||||||
|
|
||||||
pub use base::Strategy;
|
pub use base::Strategy;
|
||||||
pub use base::StrategyFn;
|
pub use base::StrategyFn;
|
||||||
|
|
||||||
|
pub use hidden_single::HiddenSingle;
|
||||||
pub use naked_single::NakedSingle;
|
pub use naked_single::NakedSingle;
|
||||||
|
|
Loading…
Reference in New Issue