Skip to content

Commit

Permalink
change [[i8; 9]; 9] to Grid
Browse files Browse the repository at this point in the history
  • Loading branch information
Nervonment committed Jun 6, 2024
1 parent 545b2b1 commit abfb58a
Show file tree
Hide file tree
Showing 14 changed files with 235 additions and 221 deletions.
2 changes: 1 addition & 1 deletion benches/solver_benches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use sudoku::{

fn benchmarks(c: &mut Criterion) {
let puzzle = random_sudoku_puzzle::<StochasticSolver<SimpleState>, AdvancedSolver<FullState>, f32>(
45, 0.0, 1000.0,
45, 80.0, 1000.0,
);
let mut solver = StochasticSolver::<SimpleState>::from(puzzle);
c.bench_function("StochasticSolver", |b| {
Expand Down
10 changes: 5 additions & 5 deletions src/bin/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ use sudoku::{
techniques::{
hidden_pair_blk, hidden_pair_col, hidden_pair_row, hidden_single_blk, hidden_single_col,
hidden_single_row, naked_pair_blk, naked_pair_col, naked_pair_row, naked_single, pointing,
}, Grid,
}
};

fn main() {
let board = random_sudoku_puzzle::<StochasticSolver<SimpleState>, AdvancedSolver<FullState>, f32>(
let grid = random_sudoku_puzzle::<StochasticSolver<SimpleState>, AdvancedSolver<FullState>, f32>(
45, 140.0, 2000.0,
);
let puzzle = FullState::from(board);
println!("{}", Grid(board));
let puzzle = FullState::from(grid);
println!("{}", grid);
let res_hidden_single_row = hidden_single_row(&puzzle);
let res_hidden_single_col = hidden_single_col(&puzzle);
let res_hidden_single_blk = hidden_single_blk(&puzzle);
Expand All @@ -36,7 +36,7 @@ fn main() {
println!("naked pair in col: {:?}", res_naked_pair_col);
println!("naked pair in blk: {:?}", res_naked_pair_blk);
println!("pointing: {:?}", res_pointing);
let mut solver2 = AdvancedSolver::<FullState>::from(board);
let mut solver2 = AdvancedSolver::<FullState>::from(grid);
solver2.have_unique_solution();
println!("{}", solver2.difficulty());
}
22 changes: 12 additions & 10 deletions src/generator.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
use rand::random;

use crate::Grid;

use super::solver::{Grader, Solver};

pub fn random_sudoku_puzzle<S1, S2, T>(
min_blank_cnt: i32, // 需要生成的题目最少空格数
min_difficulty: T, // 题目最小难度分数
max_difficulty: T, // 题目最大难度分数
) -> [[i8; 9]; 9]
) -> Grid
where
S1: Solver + From<[[i8; 9]; 9]>,
S2: Solver + Grader<T> + From<[[i8; 9]; 9]>,
S1: Solver + From<Grid>,
S2: Solver + Grader<T> + From<Grid>,
T: PartialOrd + From<i8>
{
loop {
// 生成随机终局
let mut puzzle = S1::from([[0; 9]; 9]).any_solution().unwrap();
let mut puzzle = S1::from(Grid([[0; 9]; 9])).any_solution().unwrap();

let mut dug = 0; // 已经挖掉的空格数
let mut trace = vec![]; // 挖空历史记录
Expand All @@ -25,7 +27,7 @@ where
let mut trace_back_cnt = 0; // 回退的次数
let trace_back_cnt_threshold = 12; // 回退次数阈值,回退次数超过此值会尝试重新生成终局

let mut difficulty: T = 0.into(); // 搜索函数在此题目上调用的次数
let mut difficulty: T = 0.into(); // 难度分数

while trace_back_cnt < trace_back_cnt_threshold
&& !(dug >= min_blank_cnt
Expand All @@ -41,11 +43,11 @@ where
for _ in 0..step {
// 随机选取非空格
let (mut r, mut c) = (random::<usize>() % 9, random::<usize>() % 9);
while puzzle[r][c] == 0 {
while puzzle.0[r][c] == 0 {
(r, c) = (random::<usize>() % 9, random::<usize>() % 9);
}
trace.push((r, c, puzzle[r][c]));
puzzle[r][c] = 0;
trace.push((r, c, puzzle.0[r][c]));
puzzle.0[r][c] = 0;
}

// 挖空后,判断是否有唯一解
Expand All @@ -61,7 +63,7 @@ where
let last = trace.pop();
if last.is_some() {
let (r, c, num) = last.unwrap();
puzzle[r][c] = num;
puzzle.0[r][c] = num;
}
}

Expand All @@ -71,7 +73,7 @@ where
let last = trace.pop();
if last.is_some() {
let (r, c, num) = last.unwrap();
puzzle[r][c] = num;
puzzle.0[r][c] = num;
}
}
dug -= trace_back_step;
Expand Down
145 changes: 145 additions & 0 deletions src/grid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
use std::fmt::Display;

#[derive(Clone, Copy)]
pub struct Grid(pub [[i8; 9]; 9]);

impl Display for Grid {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let grid = self.0.map(|row| {
row.map(|cell| {
if cell > 0 {
(cell as u8 + 48) as char
} else {
' '
}
})
});
writeln!(f, "┏━━━┯━━━┯━━━┳━━━┯━━━┯━━━┳━━━┯━━━┯━━━┓")?;
writeln!(
f,
"┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃",
grid[0][0],
grid[0][1],
grid[0][2],
grid[0][3],
grid[0][4],
grid[0][5],
grid[0][6],
grid[0][7],
grid[0][8],
)?;
writeln!(f, "┠───┼───┼───╂───┼───┼───╂───┼───┼───┨")?;
writeln!(
f,
"┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃",
grid[1][0],
grid[1][1],
grid[1][2],
grid[1][3],
grid[1][4],
grid[1][5],
grid[1][6],
grid[1][7],
grid[1][8],
)?;
writeln!(f, "┠───┼───┼───╂───┼───┼───╂───┼───┼───┨")?;
writeln!(
f,
"┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃",
grid[2][0],
grid[2][1],
grid[2][2],
grid[2][3],
grid[2][4],
grid[2][5],
grid[2][6],
grid[2][7],
grid[2][8],
)?;
writeln!(f, "┣━━━┿━━━┿━━━╋━━━┿━━━┿━━━╋━━━┿━━━┿━━━┫")?;
writeln!(
f,
"┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃",
grid[3][0],
grid[3][1],
grid[3][2],
grid[3][3],
grid[3][4],
grid[3][5],
grid[3][6],
grid[3][7],
grid[3][8],
)?;
writeln!(f, "┠───┼───┼───╂───┼───┼───╂───┼───┼───┨")?;
writeln!(
f,
"┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃",
grid[4][0],
grid[4][1],
grid[4][2],
grid[4][3],
grid[4][4],
grid[4][5],
grid[4][6],
grid[4][7],
grid[4][8],
)?;
writeln!(f, "┠───┼───┼───╂───┼───┼───╂───┼───┼───┨")?;
writeln!(
f,
"┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃",
grid[5][0],
grid[5][1],
grid[5][2],
grid[5][3],
grid[5][4],
grid[5][5],
grid[5][6],
grid[5][7],
grid[5][8],
)?;
writeln!(f, "┣━━━┿━━━┿━━━╋━━━┿━━━┿━━━╋━━━┿━━━┿━━━┫")?;
writeln!(
f,
"┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃",
grid[6][0],
grid[6][1],
grid[6][2],
grid[6][3],
grid[6][4],
grid[6][5],
grid[6][6],
grid[6][7],
grid[6][8],
)?;
writeln!(f, "┠───┼───┼───╂───┼───┼───╂───┼───┼───┨")?;
writeln!(
f,
"┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃",
grid[7][0],
grid[7][1],
grid[7][2],
grid[7][3],
grid[7][4],
grid[7][5],
grid[7][6],
grid[7][7],
grid[7][8],
)?;
writeln!(f, "┠───┼───┼───╂───┼───┼───╂───┼───┼───┨")?;
writeln!(
f,
"┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃ {} │ {} │ {} ┃",
grid[8][0],
grid[8][1],
grid[8][2],
grid[8][3],
grid[8][4],
grid[8][5],
grid[8][6],
grid[8][7],
grid[8][8],
)?;
write!(f, "┗━━━┷━━━┷━━━┻━━━┷━━━┷━━━┻━━━┷━━━┷━━━┛")
}
}
24 changes: 13 additions & 11 deletions src/judge.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use crate::Grid;

use super::utils::coord_2_block;

// 返回 (
// board是否为有效的部分解
// board是否为有效的完全解
// board中违反约束的格子
// )
pub fn judge_sudoku(board: &[[i8; 9]; 9]) -> (bool, bool, [[bool; 9]; 9]) {
pub fn judge_sudoku(board: &Grid) -> (bool, bool, [[bool; 9]; 9]) {
let mut row: [[(i8, i8); 10]; 9] = [[(-1, -1); 10]; 9];
let mut col: [[(i8, i8); 10]; 9] = [[(-1, -1); 10]; 9];
let mut block: [[(i8, i8); 10]; 9] = [[(-1, -1); 10]; 9];
Expand All @@ -14,29 +16,29 @@ pub fn judge_sudoku(board: &[[i8; 9]; 9]) -> (bool, bool, [[bool; 9]; 9]) {
let mut valid_cond = [[true; 9]; 9];
for r in 0..9 {
for c in 0..9 {
if board[r][c] > 0 {
if board.0[r][c] > 0 {
let b = coord_2_block(r, c);
if row[r][board[r][c] as usize] != (-1, -1) {
if row[r][board.0[r][c] as usize] != (-1, -1) {
valid = false;
valid_cond[r][c] = false;
let (r1, c1) = row[r][board[r][c] as usize];
let (r1, c1) = row[r][board.0[r][c] as usize];
valid_cond[r1 as usize][c1 as usize] = false;
}
if col[c][board[r][c] as usize] != (-1, -1) {
if col[c][board.0[r][c] as usize] != (-1, -1) {
valid = false;
valid_cond[r][c] = false;
let (r1, c1) = col[c][board[r][c] as usize];
let (r1, c1) = col[c][board.0[r][c] as usize];
valid_cond[r1 as usize][c1 as usize] = false;
}
if block[b][board[r][c] as usize] != (-1, -1) {
if block[b][board.0[r][c] as usize] != (-1, -1) {
valid = false;
valid_cond[r][c] = false;
let (r1, c1) = block[b][board[r][c] as usize];
let (r1, c1) = block[b][board.0[r][c] as usize];
valid_cond[r1 as usize][c1 as usize] = false;
}
row[r][board[r][c] as usize] = (r as i8, c as i8);
col[c][board[r][c] as usize] = (r as i8, c as i8);
block[b][board[r][c] as usize] = (r as i8, c as i8);
row[r][board.0[r][c] as usize] = (r as i8, c as i8);
col[c][board.0[r][c] as usize] = (r as i8, c as i8);
block[b][board.0[r][c] as usize] = (r as i8, c as i8);
} else {
full = false;
}
Expand Down
Loading

0 comments on commit abfb58a

Please sign in to comment.