use selen::prelude::*;
use std::time::Instant;
fn main() {
println!("๐ N-Queens Problem Solver (New API)");
println!("====================================\n");
let n = 8;
println!("๐ Solving {}-Queens problem", n);
let start = Instant::now();
match solve_n_queens(n) {
Some(solution) => {
let duration = start.elapsed();
println!("โ
Solution found in {:.3}ms!", duration.as_secs_f64() * 1000.0);
print_board(&solution, n);
}
None => {
println!("โ No solution found");
}
}
}
fn solve_n_queens(n: usize) -> Option<Vec<i32>> {
let mut m = Model::default();
let queen_rows = m.ints(n, 1, n as i32);
m.alldiff(&queen_rows);
let mut ascending_diagonals = Vec::new();
for (i, &queen_row) in queen_rows.iter().enumerate() {
let diagonal = add(queen_row, int(i as i32));
ascending_diagonals.push(diagonal);
}
let ascending_vars: Vec<_> = ascending_diagonals.iter()
.map(|expr| {
let var = m.int(1 - n as i32, 2 * n as i32);
m.new(expr.clone().eq(var));
var
})
.collect();
m.alldiff(&ascending_vars);
let mut descending_diagonals = Vec::new();
for (i, &queen_row) in queen_rows.iter().enumerate() {
let diagonal = sub(queen_row, int(i as i32));
descending_diagonals.push(diagonal);
}
let descending_vars: Vec<_> = descending_diagonals.iter()
.map(|expr| {
let var = m.int(1 - n as i32, n as i32);
m.new(expr.clone().eq(var));
var
})
.collect();
m.alldiff(&descending_vars);
match m.solve() {
Ok(sol) => {
let positions: Vec<i32> = queen_rows.iter()
.map(|&var| sol.get_int(var))
.collect();
Some(positions)
}
Err(_) => None,
}
}
fn print_board(solution: &[i32], n: usize) {
println!("\n๐ Solution:");
print!(" ");
for col in 1..=n {
print!("{:2} ", col);
}
println!();
for row in 1..=(n as i32) {
print!("{:2} ", row);
for col in 0..n {
if solution[col] == row {
print!(" โ ");
} else {
print!(" ยท ");
}
}
println!();
}
println!();
}