pub struct DlxBuilder { /* private fields */ }
Expand description
Builder for Dlx
Implementations§
Source§impl DlxBuilder
impl DlxBuilder
Sourcepub fn new(n_primary: usize, n_secondary: usize) -> Self
pub fn new(n_primary: usize, n_secondary: usize) -> Self
Creates an empty Dlx instance with the specified number of primary and secondary items but no options. Primary items are automatically numbered starting at 1 and secondary item numbers follow consecutively after primary items.
§Panics
If too many items (n_primary + n_secondary
) exceeds memory or usize
limitations.
Examples found in repository?
examples/sudoku.rs (line 24)
19pub fn solve(puzzle: &str) -> Option<String> {
20 if puzzle.len() != 81 {
21 return None;
22 }
23
24 let mut builder = DlxBuilder::new(9 * 9 * 4, 0);
25 let mut givens = IntSet::<{ (324 + 63) / 64 }>::new();
26
27 // add puzzle givens
28 for (i, ch) in puzzle.chars().enumerate() {
29 let Some(digit) = ch.to_digit(10) else {
30 continue;
31 };
32 if !(1..=9).contains(&digit) {
33 continue;
34 }
35 let digit = (digit - 1) as usize;
36 let option = sudoku_items(i, digit);
37 builder.add_option(&option);
38 for &item in &option {
39 givens.insert(item);
40 }
41 }
42
43 // add all options that do not conflict with givens
44 for cell in 0..81 {
45 for digit in 0..9 {
46 let option = sudoku_items(cell, digit);
47 if option.iter().any(|&i| givens.get(i)) {
48 continue;
49 }
50 builder.add_option(&option);
51 }
52 }
53
54 let mut ec = MrvExactCoverSearch::new(builder.build());
55 ec.search();
56
57 let solution = ec.current_solution()?;
58 let mut result = vec![b' '; 81];
59 const DIGIT_BYTES: &[u8] = b"123456789";
60 for option in solution {
61 let Ok(option): Result<[usize; 4], _> = option.try_into() else {
62 unreachable!()
63 };
64 let [cell, digit] = sudoku_invert_items(&option);
65 result[cell] = DIGIT_BYTES[digit];
66 }
67 Some(String::from_utf8(result).expect("valid utf8 that we constructed ourselves"))
68}
Sourcepub fn add_option<'a, I: IntoIterator<Item = &'a usize>>(
&mut self,
option: I,
) -> &mut Self
pub fn add_option<'a, I: IntoIterator<Item = &'a usize>>( &mut self, option: I, ) -> &mut Self
Adds option represented as a sorted (ascending order) collection of unique item indices.
Item indices start at 1 (index 0 is reserved). Empty options are silently ignored.
§Panics
- If an item index is encountered that is outside the bounds established
by the
new
call (1..=n_primary + n_secondary
). - If option items are not listed in ascending order or include duplicate items
Examples found in repository?
examples/sudoku.rs (line 37)
19pub fn solve(puzzle: &str) -> Option<String> {
20 if puzzle.len() != 81 {
21 return None;
22 }
23
24 let mut builder = DlxBuilder::new(9 * 9 * 4, 0);
25 let mut givens = IntSet::<{ (324 + 63) / 64 }>::new();
26
27 // add puzzle givens
28 for (i, ch) in puzzle.chars().enumerate() {
29 let Some(digit) = ch.to_digit(10) else {
30 continue;
31 };
32 if !(1..=9).contains(&digit) {
33 continue;
34 }
35 let digit = (digit - 1) as usize;
36 let option = sudoku_items(i, digit);
37 builder.add_option(&option);
38 for &item in &option {
39 givens.insert(item);
40 }
41 }
42
43 // add all options that do not conflict with givens
44 for cell in 0..81 {
45 for digit in 0..9 {
46 let option = sudoku_items(cell, digit);
47 if option.iter().any(|&i| givens.get(i)) {
48 continue;
49 }
50 builder.add_option(&option);
51 }
52 }
53
54 let mut ec = MrvExactCoverSearch::new(builder.build());
55 ec.search();
56
57 let solution = ec.current_solution()?;
58 let mut result = vec![b' '; 81];
59 const DIGIT_BYTES: &[u8] = b"123456789";
60 for option in solution {
61 let Ok(option): Result<[usize; 4], _> = option.try_into() else {
62 unreachable!()
63 };
64 let [cell, digit] = sudoku_invert_items(&option);
65 result[cell] = DIGIT_BYTES[digit];
66 }
67 Some(String::from_utf8(result).expect("valid utf8 that we constructed ourselves"))
68}
Sourcepub fn build(self) -> Dlx
pub fn build(self) -> Dlx
Consumes the builder and returns the completed Dlx
Examples found in repository?
examples/sudoku.rs (line 54)
19pub fn solve(puzzle: &str) -> Option<String> {
20 if puzzle.len() != 81 {
21 return None;
22 }
23
24 let mut builder = DlxBuilder::new(9 * 9 * 4, 0);
25 let mut givens = IntSet::<{ (324 + 63) / 64 }>::new();
26
27 // add puzzle givens
28 for (i, ch) in puzzle.chars().enumerate() {
29 let Some(digit) = ch.to_digit(10) else {
30 continue;
31 };
32 if !(1..=9).contains(&digit) {
33 continue;
34 }
35 let digit = (digit - 1) as usize;
36 let option = sudoku_items(i, digit);
37 builder.add_option(&option);
38 for &item in &option {
39 givens.insert(item);
40 }
41 }
42
43 // add all options that do not conflict with givens
44 for cell in 0..81 {
45 for digit in 0..9 {
46 let option = sudoku_items(cell, digit);
47 if option.iter().any(|&i| givens.get(i)) {
48 continue;
49 }
50 builder.add_option(&option);
51 }
52 }
53
54 let mut ec = MrvExactCoverSearch::new(builder.build());
55 ec.search();
56
57 let solution = ec.current_solution()?;
58 let mut result = vec![b' '; 81];
59 const DIGIT_BYTES: &[u8] = b"123456789";
60 for option in solution {
61 let Ok(option): Result<[usize; 4], _> = option.try_into() else {
62 unreachable!()
63 };
64 let [cell, digit] = sudoku_invert_items(&option);
65 result[cell] = DIGIT_BYTES[digit];
66 }
67 Some(String::from_utf8(result).expect("valid utf8 that we constructed ourselves"))
68}
Trait Implementations§
Source§impl AsRef<Dlx> for DlxBuilder
Provides a read-only view into the underlying Dlx
impl AsRef<Dlx> for DlxBuilder
Provides a read-only view into the underlying Dlx
Source§impl From<DlxBuilder> for Dlx
impl From<DlxBuilder> for Dlx
Source§fn from(value: DlxBuilder) -> Self
fn from(value: DlxBuilder) -> Self
Converts to this type from the input type.
Auto Trait Implementations§
impl Freeze for DlxBuilder
impl RefUnwindSafe for DlxBuilder
impl Send for DlxBuilder
impl Sync for DlxBuilder
impl Unpin for DlxBuilder
impl UnwindSafe for DlxBuilder
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more