deepseek改写的dlx算法求解数独rust程序
上文提到,DeepSeek改写的dlx算法rust程序数组越界,经过调试,找到的越界的数组,通过改大其大小解决了,但不知原因,因为原始C程序并没有报错,无论如何,程序正常运行了,效率也挺高。
use std::io::{self, BufRead};
use std::time::Instant;const XSIZE: usize = 5;
const SIZE: usize = XSIZE * XSIZE;
const MAX_SUDOKU: usize = SIZE * SIZE;
const MAX_C: usize = SIZE * SIZE * 4;
const MAX_R: usize = SIZE * SIZE * SIZE;
const MAX_LINK: usize = MAX_C * MAX_R;struct DLXSolver {l: Vec<usize>,r: Vec<usize>,u: Vec<usize>,d: Vec<usize>,c: Vec<usize>,o: Vec<usize>,s: Vec<usize>,h: Vec<usize>,node_number: usize,record_number: usize,ans: Vec<usize>,record: Vec<usize>,
}impl DLXSolver {fn new() -> Self {Self {l: vec![0; MAX_LINK],r: vec![0; MAX_LINK],u: vec![0; MAX_LINK],d: vec![0; MAX_LINK],c: vec![0; MAX_LINK],o: vec![0; MAX_LINK],s: vec![0; MAX_C+1], //原始C程序大小为MAX_C 在rust中索引越界h: vec![0; MAX_R+1], //原始C程序大小为MAX_R 在rust中索引越界node_number: 0,record_number: 0,ans: vec![0; MAX_SUDOKU],record: vec![0; MAX_R],}}// Dancing Links初始化fn init(&mut self) {for i in 0..=MAX_C {self.l[i] = if i == 0 { MAX_C } else { i - 1 };self.r[i] = if i == MAX_C { 0 } else { i + 1 };self.u[i] = i;self.d[i] = i;self.c[i] = i;self.o[i] = 0;}self.node_number = MAX_C + 1;self.record_number = 0;// 在Rust中,vec已经初始化为0,不需要额外memset}// 插入节点fn insert(&mut self, i: usize, j: usize) {//print!("{} ", j); if self.h[i] != 0 {self.l[self.node_number] = self.l[self.h[i]];self.r[self.node_number] = self.h[i];self.l[self.r[self.node_number]] = self.node_number;self.r[self.l[self.node_number]] = self.node_number;} else {self.l[self.node_number] = self.node_number;self.r[self.node_number] = self.node_number;self.h[i] = self.node_number;}self.u[self.node_number] = self.u[j];self.d[self.node_number] = j;self.u[self.d[self.node_number]] = self.node_number;self.d[self.u[self.node_number]] = self.node_number;self.c[self.node_number] = j;self.o[self.node_number] = i;self.s[j] += 1;self.node_number += 1;}// 移除列fn remove(&mut self, col: usize) {self.l[self.r[col]] = self.l[col];self.r[self.l[col]] = self.r[col];let mut i = self.d[col];while i != col {let mut j = self.r[i];while j != i {self.u[self.d[j]] = self.u[j];self.d[self.u[j]] = self.d[j];self.s[self.c[j]] -= 1;j = self.r[j];}i = self.d[i];}}// 恢复列fn resume(&mut self, col: usize) {let mut i = self.u[col];while i != col {let mut j = self.l[i];while j != i {self.u[self.d[j]] = j;self.d[self.u[j]] = j;self.s[self.c[j]] += 1;j = self.l[j];}i = self.u[i];}self.l[self.r[col]] = col;self.r[self.l[col]] = col;}// 添加数独约束fn add(&mut self, i: usize, j: usize, k: usize) {let row = i * MAX_SUDOKU + j * SIZE + k + 1;// 格子约束self.insert(row, i * SIZE + j + 1);// 行约束self.insert(row, i * SIZE + k + MAX_SUDOKU + 1);// 列约束self.insert(row, j * SIZE + MAX_SUDOKU * 2 + k + 1);// 宫约束self.insert(row,(i / XSIZE * XSIZE + j / XSIZE) * SIZE + MAX_SUDOKU * 3 + k + 1,);}// 构建DLX矩阵fn build(&mut self, state: &[usize]) {for i in 0..SIZE {for j in 0..SIZE {let pos = i * SIZE + j;if state[pos] != 0 {self.add(i, j, state[pos] - 1);} else {for k in 0..SIZE {self.add(i, j, k);}}}}}// DLX搜索fn dfs(&mut self, k: usize) -> bool {if self.r[0] == 0 {self.record_number = k;return true;}let mut count = MAX_R;let mut selected_col = 0;let mut i = self.r[0];while i != 0 {if self.s[i] < count {count = self.s[i];selected_col = i;if count == 1 {break;}}i = self.r[i];}self.remove(selected_col);let mut current = self.d[selected_col];while current != selected_col {let mut j = self.r[current];while j != current {self.remove(self.c[j]);j = self.r[j];}self.record[k] = self.o[current];if self.dfs(k + 1) {return true;}j = self.l[current];while j != current {self.resume(self.c[j]);j = self.l[j];}current = self.d[current];}self.resume(selected_col);false}// 输出结果fn output(&mut self) {for i in 0..self.record_number {let idx = (self.record[i] - 1) / SIZE;let value = ((self.record[i] - 1) % SIZE) + 1;self.ans[idx] = value;}for i in 0..SIZE {for j in 0..SIZE {let ch = (self.ans[i * SIZE + j] as u8 + b'A' - 1) as char;print!("{}", ch);}println!();}println!();}
}// 输入处理
fn input() -> Option<Vec<usize>> {let stdin = io::stdin();let mut lines = stdin.lock().lines();let mut buffer = Vec::new();for _ in 0..SIZE {if let Some(Ok(line)) = lines.next() {if line.is_empty() { return None; }buffer.push(line);} else {return None;}}let mut state = vec![0; MAX_SUDOKU];for (i, line) in buffer.iter().enumerate() {for (j, ch) in line.chars().enumerate() {let pos = i * SIZE + j;if ch == '-' {state[pos] = 0;} else {state[pos] = (ch as u8 - b'A' + 1) as usize;}}}Some(state)
}fn main() {while let Some(state) = input() {let start = Instant::now();let mut solver = DLXSolver::new();solver.init();solver.build(&state);if solver.dfs(0) {solver.output();println!("Time: {} ms", start.elapsed().as_millis());} else {println!("No solution found");}}
}#[cfg(test)]
mod tests {use super::*;#[test]fn test_solver_initialization() {let solver = DLXSolver::new();assert_eq!(solver.l.len(), MAX_LINK);assert_eq!(solver.r.len(), MAX_LINK);assert_eq!(solver.ans.len(), MAX_SUDOKU);}
}
运行示例
/par/selen/selen-main# cargo run --release --example dlx
PWG--X-D---J---A-R--HUN-Q
--T--SOP-----EXD-BNW--R-G
IBL-----TKM--G-----F--JYA
D---S---N-H--WUJ-IGQ-----
R-----AQJ-KOS--L-T---M---
-GAC--L-----P--HTK-----IU
-F-J--BUR-LSW-----XPA--N-
HT-RPK--X-I---C---V-L--JD
-----A--IVD-----QWB-XHM--
OU-QIH-----RGB--A-----S--
-D-P---N---V-J--KQH-UXI--
-JKV-----UXC-QAG--R-E---N
----QJD--T-----Y--IEP----
Y---F-P--SNM-HIW-----LDR-
--WUT-GRM--D-F---C---Q-S-
--J-----Q--GNL-----DYP-VS
--NKM-JSL-----PRO--G-----
EP--X-N---Q---K-S--AFJ-DR
-R--CUK-----FMV-YXJ--E-W-
LS-----HBW--I-----F--GOK-
---I---L-G--JXN-ESA-----M
-----VWX-NUL--Q-I---J---C
WYR--D-----I--TFX-----LAP
N-S--OCA-IGE-----HKL--Q--
K-PEA--M-H---Y---J-N--XBW
PWGMOXIDYLBJVTFACRSKHUNEQ
JQTFKSOPHMAYCEXDUBNWIVRLG
IBLHVWUCTKMNQGRXPOEFSDJYA
DAYXSBVENRHPLWUJMIGQOKCFT
RCUNEGAQJFKOSIDLVTYHWMPXB
BGACWNLFSJEXPVMHTKDOQRYIU
VFDJYCBURQLSWKHIGMXPAOTNE
HTMRPKEWXOIQANCSFYVULBGJD
SKELNAYGIVDTUOJCQWBRXHMPF
OUXQIHMTDPFRGBYEANLJVWSCK
CDBPRLFNWAOVEJSMKQHTUXIGY
MJKVLIHYOUXCBQAGDPRSEFWTN
XNHSQJDBCTRWKUGYLFIEPAVMO
YEOGFQPKVSNMTHIWBAUXCLDRJ
AIWUTEGRMXPDYFLNJCOVBQKSH
FOJABRXIQCTGNLWKHEMDYPUVS
UHNKMFJSLEYBXDPROVWGTCAQI
EPIWXMNVGYQUOCKBSLTAFJHDR
GRQTCUKOADSHFMVPYXJINEBWL
LSVYDPTHBWJAIREQNUFCMGOKX
QVCIHYRLPGWKJXNUESABDTFOM
TMFBGVWXKNULRAQOIDPYJSEHC
WYROUDQJEBVIHSTFXGCMKNLAP
NXSDJOCAFIGEMPBTWHKLRYQUV
KLPEATSMUHCFDYOVRJQNGIXBWTime: 2 ms
把const XSIZE: usize = 5;
中的5改为3和4,就能求9x9和16x16数独。
cargo run --release --example dlxCompiling selen v0.12.4 (/par/selen/selen-main)Finished `release` profile [optimized] target(s) in 4.73sRunning `target/release/examples/dlx`
--A----C-----O-I
-J--A-B-P-CGF-H-
--D--F-I-E----P-
-G-EL-H----M-J--
----E----C--G---
-I--K-GA-B---E-J
D-GP--J-F----A--
-E---C-B--DP--O-
E--F-M--D--L-K-A
-C--------O-I-L-
H-P-C--F-A--B---
---G-OD---J----H
K---J----H-A-P-L
--B--P--E--K--A-
-H--B--K--FI-C--
--F---C--D--H-N-
FPAHMJECNLBDKOGI
OJMIANBDPKCGFLHE
LNDKGFOIJEAHMBPC
BGCELKHPOFIMAJDN
MFHBELPOACKJGNID
CILNKDGAHBMOPEFJ
DOGPIHJMFNLECAKB
JEKAFCNBGIDPLHOM
EBOFPMIJDGHLNKCA
NCJDHBAEKMOFIGLP
HMPLCGKFIAENBDJO
AKIGNODLBPJCEFMH
KDEMJIFNCHGAOPBL
GLBCDPMHEONKJIAF
PHNOBALKMJFIDCEG
IAFJOECGLDPBHMNKTime: 4 ms