-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy path16x16-sudoku.rs
116 lines (100 loc) · 2.7 KB
/
16x16-sudoku.rs
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use std::io;
const N: usize = 4;
const N_2: usize = N * N;
const POSS: u32 = (1 << N_2) - 1;
const BASE: u8 = b'A';
const VIDE: u8 = b'.';
macro_rules! bx {
($j:expr, $k:expr) => {
((($j) / N) * N + ($k) / N)
};
}
macro_rules! parse_input {
($t:ident) => {{
let mut input_line = String::new();
io::stdin().read_line(&mut input_line).unwrap();
input_line.trim_matches('\n').parse::<$t>().unwrap()
}}
}
fn backtrack(
pos: &mut Vec<usize>,
candrow: &mut [u32; N_2],
candcol: &mut [u32; N_2],
candbox: &mut [u32; N_2],
solution: &mut [[u8; N_2]; N_2],
) -> bool {
if pos.is_empty() {
return true;
}
let mut mini = 2 * N_2;
let mut best_idx = 0;
for (idx, &p) in pos.iter().enumerate() {
let i = p / N_2;
let j = p % N_2;
let b = bx!(i, j);
let candidates = candrow[i] & candcol[j] & candbox[b];
let nb = candidates.count_ones() as usize;
if nb < mini {
mini = nb;
best_idx = idx;
}
}
let p = pos.remove(best_idx);
let i = p / N_2;
let j = p % N_2;
let b = bx!(i, j);
let mut bitset = candrow[i] & candcol[j] & candbox[b];
while bitset != 0 {
let k = bitset.trailing_zeros();
bitset &= !(1 << k);
candrow[i] &= !(1 << k);
candcol[j] &= !(1 << k);
candbox[b] &= !(1 << k);
if backtrack(pos, candrow, candcol, candbox, solution) {
solution[i][j] = BASE + k as u8;
return true;
}
candrow[i] |= 1 << k;
candcol[j] |= 1 << k;
candbox[b] |= 1 << k;
}
pos.insert(0, p);
false
}
fn display(grid: &[[u8; N_2]; N_2]) {
for i in 0..N_2 {
let line: String = grid[i].iter().map(|&c| c as char).collect();
println!("{}", line);
}
}
fn main() {
let mut row = [POSS; N_2];
let mut col = [POSS; N_2];
let mut bx = [POSS; N_2];
let mut grid = [[0u8; N_2]; N_2];
let mut res = [[0u8; N_2]; N_2];
let mut pos = Vec::new();
for l in 0..N_2 {
for (j, &ch) in parse_input!(String).as_bytes().iter().take(N_2).enumerate() {
grid[l][j] = ch;
}
}
for i in 0..N_2 {
for j in 0..N_2 {
let b = bx!(i, j);
let val = grid[i][j];
if val != VIDE {
let k = (val - BASE) as u32;
row[i] &= !(1 << k);
col[j] &= !(1 << k);
bx[b] &= !(1 << k);
res[i][j] = val;
} else {
pos.push(i * N_2 + j);
}
}
}
if backtrack(&mut pos, &mut row, &mut col, &mut bx, &mut res) {
display(&res);
}
}