1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use crate::Solver;

/// Implements solution to the N queens problem
///
/// ```
///# use dlx_rs::queens::Queens;
/// let n_queens_solutions = vec![0,1,0,0,2,10,4,40,92,352,724];
/// for i in 1..=10 {
///     let qi = Queens::new(i);
///     assert_eq!(qi.count(), n_queens_solutions[i]);
/// }
/// ```
pub struct Queens {
    n: usize,
    solver: Solver,
}

impl Queens {
    /// Creates new `Queens` set up with constraints for the `n` queens problem
    pub fn new(n: usize) -> Queens {
        // Create blank solver

        // Add constraints

        // What are the constraints?
        // We are putting N queens on an NxN chess board

        // 1. Each of the N columns must have exactly 1 queen on it
        // 2. Each of the N rows must have exactly 1 queen on it
        // 3. Each of the 2*N-1 right diagonals may have at most one queen
        // 4. Each of the 2*N-1 left diagonals may have at most one queen
        // 5. Each of the N^2 squares may have at most one queen

        // So this gives us 2*N mandatory items, and N^2 + 6*N -2 optional ones

        let mut solver = Solver::new_optional(2 * n, n * n + 6 * n - 2);

        // Now add options: each option corresponds to a queen in a particular

        for r in 1..=n {
            for c in 1..=n {
                let con_name = format!("R{}C{}", r, c);
                // 1 -> N
                let col_con = c;
                // N+1 -> 2*N
                let row_con = n + r;
                // 2*N+1 -> 4*N - 1
                let rd_con = 2 * n + c - r + n;
                // 4*N ->  6*N - 2
                let ld_con = 4 * n - 1 + r + c - 1;
                // 6*N-1 -> N**2 + 6*N - 2
                let is_queen = 6 * n - 2 + r + n * (c - 1);

                solver.add_option(&con_name, &[col_con, row_con, rd_con, ld_con, is_queen]);
            }
        }

        Queens { solver, n }
    }
}

impl Iterator for Queens {
    type Item = Vec<(usize, usize)>;
    /// Returns the next solution, which is a vector of tuples denoting the Row and Column of the N queens in the solution
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(sol) = self.solver.next() {
            let mut n_queens_solved = Vec::with_capacity(self.n);
            for i in sol {
                let i = i.as_str();
                let s: Vec<&str> = i.split(&['R', 'C']).collect(); //.split('C').split('#');
                let r: usize = s[1].parse().unwrap();
                let c: usize = s[2].parse().unwrap();
                n_queens_solved.push((r, c));
            }
            Some(n_queens_solved)
        } else {
            None
        }
    }
}