1#![allow(incomplete_features)]
5#![feature(adt_const_params,generic_const_exprs)]
6
7use ranged_integers::*;
8
9pub const ROW_SIZE : usize = 9;
10
11pub type Val = Ranged<0, 9>;
12pub type RowIndex = Ranged<0, {({ROW_SIZE - 1}) as _}>;
13pub type Sudoku = [[Val; 9]; 9];
14
15pub fn is_valid(val: Val, x: RowIndex, y: RowIndex, sudoku_ar: &Sudoku) -> bool {
16 r!(0..=8).into_iter().all( |i|
17 sudoku_ar[x][i] != val &&
18 sudoku_ar[i][y] != val && {
19 r!(0..=2).into_iter().all(|i| r!(0..=2).into_iter().all(|j|
20 sudoku_ar[x / r!(3) * r!(3) + i][y / r!(3) * r!(3) + j] != val
21 ))
22 }
23 )
24}
25
26pub fn place_number(pos: Ranged<0, 80>, sudoku_ar: &mut Sudoku) -> bool {
27 pos.iter_up()
28 .find_map(|p| {
29 let (x, y) = (p % r!(9), p / r!(9));
30 if sudoku_ar[x][y] == r!(0) {Some((x,y))} else {None}
31 })
32 .is_none_or(|(x, y)| {
33 for n in r!(1..=9) {
34 if is_valid(n.expand(), x, y, sudoku_ar) {
35 sudoku_ar[x][y] = n.expand();
36 let next = if let Some(next) = (pos + r!(1)).fit() {next} else {return true};
37 if place_number(next,sudoku_ar) {
38 return true;
39 }
40 sudoku_ar[x][y] = r!([]0);
41 }
42 }
43 false
44 })
45}
46
47pub fn pretty_print(sudoku_ar: Sudoku) {
48 let line_sep = "------+-------+------";
49 println!("{line_sep}");
50 for (i, row) in sudoku_ar.iter().enumerate() {
51 for (j, val) in row.iter().enumerate() {
52 print!("{val} ");
53 if j == 2 || j == 5 {
54 print!("| ");
55 }
56 }
57 println!();
58 if i % 3 == 2 {
59 println!("{line_sep}");
60 }
61 }
62}
63
64fn solve(sudoku_ar: &mut Sudoku)->bool {
65 place_number(r!([] 0), sudoku_ar)
66}
67
68macro_rules! rangedarr {
69 ($($e:literal),* $(,)?) => { [$( r!([] $e) ),*] };
70}
71
72fn main() {
73 let mut sudoku_ar: Sudoku = [
74 rangedarr![8, 5, 0, 0, 0, 2, 4, 0, 0],
75 rangedarr![7, 2, 0, 0, 0, 0, 0, 0, 9],
76 rangedarr![0, 0, 4, 0, 0, 0, 0, 0, 0],
77 rangedarr![0, 0, 0, 1, 0, 7, 0, 0, 2],
78 rangedarr![3, 0, 5, 0, 0, 0, 9, 0, 0],
79 rangedarr![0, 4, 0, 0, 0, 0, 0, 0, 0],
80 rangedarr![0, 0, 0, 0, 8, 0, 0, 7, 0],
81 rangedarr![0, 1, 7, 0, 0, 0, 0, 0, 0],
82 rangedarr![0, 0, 0, 0, 3, 6, 0, 4, 0],
83 ];
84
85 if solve(&mut sudoku_ar) {
86 pretty_print(sudoku_ar);
87 }
88 else {
89 println!("Unsolvable");
90 }
91}