1use crate::{
2 grid::{Column, Grid, Node},
3 ExactCover,
4};
5use core::iter;
6use std::collections::VecDeque;
7
8#[derive(Debug)]
10pub struct Solver<'e, E: ExactCover> {
11 problem: &'e E,
12
13 grid: Grid,
15 partial_solution: Vec<usize>,
16 stack: Vec<Frame>,
17}
18
19#[derive(Debug)]
20enum FrameState {
21 Cover,
23 Uncover,
25}
26
27#[derive(Debug)]
28struct Frame {
29 #[allow(dead_code)]
30 min_column: *mut Column,
31 selected_rows: VecDeque<(usize, Vec<*mut Column>)>,
32 state: FrameState,
33}
34
35impl<'e, E> Solver<'e, E>
36where
37 E: ExactCover,
38{
39 pub fn new(problem: &'e E) -> Self {
41 let grid = Self::populate_grid(problem);
42
43 let mut solver = Self {
44 problem,
45
46 grid,
47 partial_solution: Vec::new(),
48 stack: Vec::new(),
49 };
50
51 if !Self::solution_test(&solver.grid, solver.problem) {
54 let min_column = Self::choose_column(&mut solver.grid, solver.problem);
55 let selected_rows = Self::select_rows_from_column(min_column);
56
57 if !selected_rows.is_empty() {
58 solver.stack.push(Frame {
59 state: FrameState::Cover,
60 min_column,
61 selected_rows,
62 });
63 }
64 }
65
66 solver
67 }
68
69 pub fn reset(&mut self) {
72 self.grid = Self::populate_grid(self.problem);
73 self.partial_solution.clear();
74 self.stack.clear();
75 }
76
77 fn populate_grid(problem: &E) -> Grid {
78 let coordinates_iter = problem
79 .possibilities()
80 .iter()
81 .enumerate()
82 .flat_map({
83 move |(row_idx, poss)| {
84 problem
85 .constraints()
86 .iter()
87 .enumerate()
88 .zip(iter::repeat((row_idx, poss)))
89 .map({
90 |((col_idx, cons), (row_idx, poss))| {
91 ((row_idx + 1, col_idx + 1), poss, cons)
92 }
93 })
94 }
95 })
96 .filter_map(|(coord, poss, cons)| {
97 if problem.satisfies(poss, cons) {
98 Some(coord)
99 } else {
100 None
101 }
102 });
103
104 Grid::new(problem.constraints().len(), coordinates_iter)
105 }
106
107 fn solution_test(grid: &Grid, problem: &E) -> bool {
108 !grid
109 .uncovered_columns()
110 .any(|column| !problem.is_optional(&problem.constraints()[Column::index(column) - 1]))
111 }
112
113 fn choose_column(grid: &mut Grid, problem: &E) -> *mut Column {
114 grid.uncovered_columns_mut()
115 .filter(|column| {
116 !problem.is_optional(&problem.constraints()[Column::index(*column as *const _) - 1])
117 })
118 .min_by_key(|column_ptr| Column::size(*column_ptr))
119 .unwrap()
120 }
121
122 fn select_rows_from_column(min_column: *mut Column) -> VecDeque<(usize, Vec<*mut Column>)> {
123 Column::rows(min_column)
124 .map(|node_ptr| {
125 (
126 Node::row_index(node_ptr),
127 Node::neighbors(node_ptr)
128 .map(Node::column_ptr)
129 .chain(iter::once(Node::column_ptr(node_ptr)))
130 .collect(),
131 )
132 })
133 .collect()
134 }
135
136 pub fn all_solutions(&mut self) -> Vec<Vec<&'e E::Possibility>> {
138 self.collect()
139 }
140
141 pub fn next_solution<'s>(&'s mut self) -> Option<Vec<&'e E::Possibility>>
143 where
144 'e: 's,
145 {
146 enum StackOp<T> {
147 Push(T),
148 Pop,
149 None,
150 }
151
152 while !self.stack.is_empty() {
153 let curr_frame = self.stack.last_mut().unwrap();
154
155 let (stack_op, possible_solution) = match curr_frame.state {
156 FrameState::Cover => {
159 let (row_index, columns) = curr_frame.selected_rows.front().unwrap();
160
161 self.partial_solution.push(row_index - 1);
162 for column_ptr in columns {
163 Column::cover(*column_ptr);
164 }
165
166 let stack_op = if Self::solution_test(&self.grid, self.problem) {
169 (StackOp::None, Some(self.partial_solution.clone()))
170 } else {
171 let min_column = Self::choose_column(&mut self.grid, self.problem);
172 let selected_rows = Self::select_rows_from_column(min_column);
173
174 if selected_rows.is_empty() {
175 (StackOp::None, None)
176 } else {
177 (
178 StackOp::Push(Frame {
179 state: FrameState::Cover,
180 min_column,
181 selected_rows,
182 }),
183 None,
184 )
185 }
186 };
187
188 curr_frame.state = FrameState::Uncover;
189 stack_op
190 }
191 FrameState::Uncover => {
194 let (_row_index, columns) = curr_frame.selected_rows.pop_front().unwrap();
195
196 for column_ptr in columns.into_iter().rev() {
197 Column::uncover(column_ptr);
198 }
199 self.partial_solution.pop();
200
201 if curr_frame.selected_rows.is_empty() {
202 (StackOp::Pop, None)
203 } else {
204 curr_frame.state = FrameState::Cover;
205 (StackOp::None, None)
206 }
207 }
208 };
209
210 match stack_op {
211 StackOp::Push(val) => {
212 self.stack.push(val);
213 }
214 StackOp::Pop => {
215 self.stack.pop();
216 }
217 StackOp::None => {}
218 }
219
220 if let Some(solution) = possible_solution {
221 return Some(
222 solution
223 .into_iter()
224 .map(|row_index| &self.problem.possibilities()[row_index])
225 .collect(),
226 );
227 }
228 }
229
230 None
231 }
232}
233
234impl<'e, E> Iterator for Solver<'e, E>
235where
236 E: ExactCover,
237{
238 type Item = Vec<&'e E::Possibility>;
239
240 fn next(&mut self) -> Option<Self::Item> {
241 self.next_solution()
242 }
243}