use log::warn;
use crate::{block::Block, board::Board, solver::probing::ProbeSolver, utils::rc::MutRc};
#[cfg(not(feature = "sat"))]
pub mod backtracking;
pub mod line;
pub mod probing;
pub mod propagation;
#[cfg(feature = "sat")]
pub mod sat;
#[cfg(not(feature = "sat"))]
pub fn run<B, S, P>(
board: MutRc<Board<B>>,
max_solutions: Option<usize>,
timeout: Option<u32>,
max_depth: Option<usize>,
) -> Result<Option<backtracking::Solver<B, P, S>>, String>
where
B: Block,
S: line::LineSolver<BlockType = B>,
P: ProbeSolver<BlockType = B>,
{
warn!("Solving with simple line propagation");
let mut solver = propagation::Solver::new(MutRc::clone(&board));
let solved_points = solver
.run::<S>(None)
.map_err(|err| format!("Bad puzzle: simple propagation failed: {:?}", err))?;
warn!("Solved {} points", solved_points.len());
if !board.read().is_solved_full() {
warn!(
"Trying to solve with backtracking (solved on {:.3}%)",
board.read().solution_rate() * 100.0
);
let mut solver =
backtracking::Solver::<_, P, S>::with_options(board, max_solutions, timeout, max_depth);
solver.run()?;
return Ok(Some(solver));
}
Ok(None)
}
#[cfg(feature = "sat")]
#[allow(clippy::needless_pass_by_value)]
pub fn run<B, S, P>(
board: MutRc<Board<B>>,
max_solutions: Option<usize>,
) -> Result<Option<impl Iterator<Item = Vec<B::Color>>>, String>
where
B: Block,
S: line::LineSolver<BlockType = B>,
P: ProbeSolver<BlockType = B>,
{
use crate::board::LineDirection;
warn!("Solving with simple line propagation");
let mut solver = propagation::Solver::new(MutRc::clone(&board));
let solved_points = solver
.run::<S>(None)
.map_err(|err| format!("Bad puzzle: simple propagation failed: {:?}", err))?;
warn!("Solved {} points", solved_points.len());
if board.read().is_solved_full() {
return Ok(None);
}
let impact = {
warn!(
"Solving with probing (solved on {:.3}%)",
board.read().solution_rate() * 100.0
);
let mut probe_solver = P::with_board(MutRc::clone(&board));
probe_solver.run_unsolved::<S>()?
};
if !board.read().is_solved_full() {
warn!(
"Trying to solve with SAT (solved on {:.3}%)",
board.read().solution_rate() * 100.0
);
let solver = sat::ClauseGenerator::with_clues(
board.read().descriptions(LineDirection::Column),
board.read().descriptions(LineDirection::Row),
board.read().make_snapshot(),
);
let solutions_iter = solver.run(impact, max_solutions);
return Ok(Some(solutions_iter));
}
Ok(None)
}