From d83f4e04dcabf802ed7f8dac4afa05fcfe1359de Mon Sep 17 00:00:00 2001 From: lashman Date: Fri, 30 May 2025 21:01:07 +0300 Subject: [PATCH] solver state and module glue --- cruciverb-core/src/solver/mod.rs | 5 ++ cruciverb-core/src/solver/state.rs | 78 ++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 cruciverb-core/src/solver/mod.rs create mode 100644 cruciverb-core/src/solver/state.rs diff --git a/cruciverb-core/src/solver/mod.rs b/cruciverb-core/src/solver/mod.rs new file mode 100644 index 0000000..efbe65e --- /dev/null +++ b/cruciverb-core/src/solver/mod.rs @@ -0,0 +1,5 @@ +pub mod candidate; +pub mod csp; +pub mod state; + +pub use csp::{SolveResult, solve}; diff --git a/cruciverb-core/src/solver/state.rs b/cruciverb-core/src/solver/state.rs new file mode 100644 index 0000000..0bb0b47 --- /dev/null +++ b/cruciverb-core/src/solver/state.rs @@ -0,0 +1,78 @@ +use crate::dict::index::WordIndex; +use crate::grid::slot::Slot; + +pub struct SolverState { + pub assignments: Vec>, + pub used_words: Vec, + pub grid_letters: Vec>>, + pub cell_domains: Vec>, + pub width: usize, + pub height: usize, +} + +impl SolverState { + pub fn new(slots: &[Slot], width: usize, height: usize, dict_size: usize) -> Self { + let all_bits = (1u32 << 26) - 1; + Self { + assignments: vec![None; slots.len()], + used_words: vec![false; dict_size], + grid_letters: vec![vec![None; width]; height], + cell_domains: vec![vec![all_bits; width]; height], + width, + height, + } + } + + pub fn init_domains(&mut self, slots: &[Slot], dict: &WordIndex) { + for slot in slots { + for (pos, &(r, c)) in slot.cells().iter().enumerate() { + let allowed = dict.allowed_letters(slot.length, pos); + if allowed != 0 { + self.cell_domains[r][c] &= allowed; + } + } + } + } + + pub fn get_domain(&self, r: usize, c: usize) -> u32 { + self.cell_domains[r][c] + } + + pub fn set_domain(&mut self, r: usize, c: usize, domain: u32) { + self.cell_domains[r][c] = domain; + } + + pub fn get_letter(&self, row: usize, col: usize) -> Option { + self.grid_letters[row][col] + } + + pub fn set_letter(&mut self, row: usize, col: usize, letter: u8) { + self.grid_letters[row][col] = Some(letter); + } + + pub fn clear_letter(&mut self, row: usize, col: usize) { + self.grid_letters[row][col] = None; + } + + pub fn mark_used(&mut self, word_idx: usize) { + self.used_words[word_idx] = true; + } + + pub fn unmark_used(&mut self, word_idx: usize) { + self.used_words[word_idx] = false; + } + + pub fn is_used(&self, word_idx: usize) -> bool { + self.used_words[word_idx] + } + + pub fn current_constraints(&self, slot: &Slot) -> Vec<(usize, u8)> { + let mut constraints = Vec::new(); + for (pos, (r, c)) in slot.cells().iter().enumerate() { + if let Some(letter) = self.get_letter(*r, *c) { + constraints.push((pos, letter)); + } + } + constraints + } +}