lisudoku_solver/solver/logical_solver/
sum_candidates.rs

1use crate::solver::Solver;
2use crate::types::CellPosition;
3use super::combinations::cell_combination_logic::CellCombinationLogic;
4use super::combinations::cell_combinations_runner::{CellCombinationsRunner, State};
5
6impl Solver {
7  pub fn detect_invalid_sum_candidates(&self, cells: &Vec<CellPosition>, sum: u32) -> Vec<(CellPosition, Vec<u32>)> {
8    let mut combinations_runner = CellCombinationsRunner::new(
9      &self, Box::new(SumCombinationsLogic::new(cells, sum))
10    );
11    let (valid_candidates, _) = combinations_runner.run();
12    self.cell_candidates_diff(cells, valid_candidates)
13  }
14}
15
16struct SumCombinationsLogic<'a> {
17  sum_left: u32,
18  cells: &'a Vec<CellPosition>,
19}
20
21impl SumCombinationsLogic<'_> {
22  pub fn new<'a>(cells: &'_ Vec<CellPosition>, sum: u32) -> SumCombinationsLogic {
23    SumCombinationsLogic {
24      cells,
25      sum_left: sum,
26    }
27  }
28}
29
30impl CellCombinationLogic for SumCombinationsLogic<'_> {
31  fn cells(&self) -> Vec<CellPosition> {
32    self.cells.to_owned()
33  }
34
35  fn is_value_valid_candidate_in_cell(&self, runner: &CellCombinationsRunner, value: u32, index: usize) -> bool {
36    // TODO: adapt to grid_size
37    // 9 + 8 + 7 + ... + (9 - x + 1) = x * (19 - x) / 2
38    let cells_left_count: u32 = runner.cells.len() as u32 - index as u32 - 1;
39    let max_sum_left = cells_left_count * (19 - cells_left_count) / 2;
40
41    if value > self.sum_left {
42      return false
43    }
44    if self.sum_left - value > max_sum_left {
45      return false
46    }
47
48    true
49  }
50
51  fn should_check_all_cells_in_set(&self) -> bool { true }
52
53  fn advance_state(&mut self, _state: &mut State, value: u32, _index: usize) {
54    self.sum_left -= value;
55  }
56
57  fn restore_state(&mut self, _state: &mut State, value: u32, _index: usize) {
58    self.sum_left += value;
59  }
60}