在微信公众号文章9行代码搞定数独Rust神器中看到,到github存储库下载了,测试了它的数独求解,还不错。
将下载的源代码包 解压缩到 /par, 然后用如下命令行编译,因为要多次测试,我把readme 中写的run改成了build。
一开始在rust 1.87上编译,报错,说要1.88版本,于是用1.88版本的docker镜像容器来编译。编译速度很快,可是也发出很多警告,绝大部分都是post!引起的。好在没有错误,成功生成了sudoku二进制文件。
cargo build --release --example sudoku
warning: use of deprecated associated function `constraints::macros::ConstraintRef::new`: Constraint macros are difficult to maintain and have limited capabilities. Use the constraint API methods directly (e.g., `model.add(x, y)` instead of `post!(model, x + y)`). This module will be removed in a future release.
--> src/constraints/macros/comparison.rs:145:53
|
145 | $crate::constraints::macros::ConstraintRef::new(0)
| ^^^
|
::: src/benchmarks/step_2_4_performance_benchmarks_simple.rs:135:5
|
135 | post!(m, density <= 7500.0);
| --------------------------- in this macro invocation
|
= note: this warning originates in the macro `$crate::post_comparison` which comes from the expansion of the macro `post` (in Nightly builds, run with -Z macro-backtrace for more info)
...
warning: `selen` (lib) generated 410 warnings (run `cargo fix --lib -p selen` to apply 8 suggestions)
Compiling selen v0.9.5 (/par/selen-main)
warning: unused variable: `easy_propagations`
--> examples/sudoku.rs:79:10
|
79 | let (easy_propagations, easy_nodes) = solve_and_display("EASY", &easy_puzzle);
| ^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_easy_propagations`
|
= note: `#[warn(unused_variables)]` on by default
warning: unused variable: `easy_nodes`
--> examples/sudoku.rs:79:29
|
79 | let (easy_propagations, easy_nodes) = solve_and_display("EASY", &easy_puzzle);
| ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_easy_nodes`
warning: unused variable: `hard_propagations`
--> examples/sudoku.rs:80:10
|
80 | let (hard_propagations, hard_nodes) = solve_and_display("HARD", &hard_puzzle);
| ^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_hard_propagations`
warning: unused variable: `hard_nodes`
--> examples/sudoku.rs:80:29
|
80 | let (hard_propagations, hard_nodes) = solve_and_display("HARD", &hard_puzzle);
| ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_hard_nodes`
warning: unused variable: `extreme_propagations`
--> examples/sudoku.rs:81:10
|
81 | let (extreme_propagations, extreme_nodes) = solve_and_display("EXTREME", &extreme_puzzle);
| ^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_extreme_propagations`
warning: unused variable: `extreme_nodes`
--> examples/sudoku.rs:81:32
|
81 | let (extreme_propagations, extreme_nodes) = solve_and_display("EXTREME", &extreme_puzzle);
| ^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_extreme_nodes`
warning: unused variable: `platinum_propagations`
--> examples/sudoku.rs:82:10
|
82 | let (platinum_propagations, platinum_nodes) = solve_and_display("PLATINUM", &platinum_puzzle);
| ^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_platinum_propagations`
warning: unused variable: `platinum_nodes`
--> examples/sudoku.rs:82:33
|
82 | let (platinum_propagations, platinum_nodes) = solve_and_display("PLATINUM", &platinum_puzzle);
| ^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_platinum_nodes`
warning: `selen` (example "sudoku") generated 8 warnings
Finished `release` profile [optimized] target(s) in 4.10s
运行结果
root@DESKTOP-59T6U68:/par/selen-main# cd target/release/examples
root@DESKTOP-59T6U68:/par/selen-main/target/release/examples# ./sudoku
🔢 Simple Sudoku Solver
======================
🧩 Solving EASY puzzle:
📊 Puzzle stats: 26 clues given, 55 empty cells
Puzzle:
┌───────┬───────┬───────┐
│ 5 3 · │ · 7 · │ · · · │
│ 6 · · │ 1 9 5 │ · · · │
│ · 9 · │ · · · │ · 6 · │
├───────┼───────┼───────┤
│ 8 · · │ · 6 · │ · · · │
│ 4 · · │ 8 · 3 │ · · 1 │
│ 7 · · │ · 2 · │ · · 6 │
├───────┼───────┼───────┤
│ · 6 · │ · · · │ · 8 · │
│ · · · │ 4 1 9 │ · · 5 │
│ · · · │ · 8 · │ · 7 · │
└───────┴───────┴───────┘
✅ Solution found in 2.306ms!
📊 Statistics: 426 propagations, 15 nodes explored
🔍 Efficiency: 28.4 propagations/node
Solution:
┌───────┬───────┬───────┐
│ 5 3 2 │ 6 7 8 │ 4 1 9 │
│ 6 7 4 │ 1 9 5 │ 2 3 8 │
│ 1 9 8 │ 3 4 2 │ 5 6 7 │
├───────┼───────┼───────┤
│ 8 1 9 │ 7 6 4 │ 3 5 2 │
│ 4 2 6 │ 8 5 3 │ 7 9 1 │
│ 7 5 3 │ 9 2 1 │ 8 4 6 │
├───────┼───────┼───────┤
│ 2 6 1 │ 5 3 7 │ 9 8 4 │
│ 3 8 7 │ 4 1 9 │ 6 2 5 │
│ 9 4 5 │ 2 8 6 │ 1 7 3 │
└───────┴───────┴───────┘
──────────────────────────────────────────────────
🧩 Solving HARD puzzle:
📊 Puzzle stats: 23 clues given, 58 empty cells
Puzzle:
┌───────┬───────┬───────┐
│ 1 · · │ · · 7 │ · 9 · │
│ · 3 · │ · 2 · │ · · 8 │
│ · · 9 │ 6 · · │ 5 · · │
├───────┼───────┼───────┤
│ · · 5 │ 3 · · │ 9 · · │
│ · 1 · │ · 8 · │ · · 2 │
│ 6 · · │ · · 4 │ · · · │
├───────┼───────┼───────┤
│ 3 · · │ · · · │ · 1 · │
│ · 4 · │ · · · │ · · 7 │
│ · · 7 │ · · · │ 3 · · │
└───────┴───────┴───────┘
✅ Solution found in 17.899ms!
📊 Statistics: 381 propagations, 17 nodes explored
🔍 Efficiency: 22.4 propagations/node
Solution:
┌───────┬───────┬───────┐
│ 1 6 2 │ 8 5 7 │ 4 9 3 │
│ 5 3 4 │ 1 2 9 │ 6 7 8 │
│ 7 8 9 │ 6 4 3 │ 5 2 1 │
├───────┼───────┼───────┤
│ 4 7 5 │ 3 1 2 │ 9 8 6 │
│ 9 1 3 │ 5 8 6 │ 7 4 2 │
│ 6 2 8 │ 7 9 4 │ 1 3 5 │
├───────┼───────┼───────┤
│ 3 5 6 │ 4 7 8 │ 2 1 9 │
│ 2 4 1 │ 9 3 5 │ 8 6 7 │
│ 8 9 7 │ 2 6 1 │ 3 5 4 │
└───────┴───────┴───────┘
──────────────────────────────────────────────────
🧩 Solving EXTREME puzzle:
📊 Puzzle stats: 21 clues given, 60 empty cells
Puzzle:
┌───────┬───────┬───────┐
│ 8 · · │ · · · │ · · · │
│ · · 3 │ 6 · · │ · · · │
│ · 7 · │ · 9 · │ 2 · · │
├───────┼───────┼───────┤
│ · 5 · │ · · 7 │ · · · │
│ · · · │ · 4 5 │ 7 · · │
│ · · · │ 1 · · │ · 3 · │
├───────┼───────┼───────┤
│ · · 1 │ · · · │ · 6 8 │
│ · · 8 │ 5 · · │ · 1 · │
│ · 9 · │ · · · │ 4 · · │
└───────┴───────┴───────┘
✅ Solution found in 25.889ms!
📊 Statistics: 477 propagations, 36 nodes explored
🔍 Efficiency: 13.2 propagations/node
Solution:
┌───────┬───────┬───────┐
│ 8 1 2 │ 7 5 3 │ 6 4 9 │
│ 9 4 3 │ 6 8 2 │ 1 7 5 │
│ 6 7 5 │ 4 9 1 │ 2 8 3 │
├───────┼───────┼───────┤
│ 1 5 4 │ 2 3 7 │ 8 9 6 │
│ 3 6 9 │ 8 4 5 │ 7 2 1 │
│ 2 8 7 │ 1 6 9 │ 5 3 4 │
├───────┼───────┼───────┤
│ 5 2 1 │ 9 7 4 │ 3 6 8 │
│ 4 3 8 │ 5 2 6 │ 9 1 7 │
│ 7 9 6 │ 3 1 8 │ 4 5 2 │
└───────┴───────┴───────┘
──────────────────────────────────────────────────
🧩 Solving PLATINUM puzzle:
📊 Puzzle stats: 17 clues given, 64 empty cells
Puzzle:
┌───────┬───────┬───────┐
│ · · · │ · · · │ · · · │
│ · · · │ · · 3 │ · 8 5 │
│ · · 1 │ · 2 · │ · · · │
├───────┼───────┼───────┤
│ · · · │ 5 · 7 │ · · · │
│ · · 4 │ · · · │ 1 · · │
│ · 9 · │ · · · │ · · · │
├───────┼───────┼───────┤
│ 5 · · │ · · · │ · 7 3 │
│ · · 2 │ · 1 · │ · · · │
│ · · · │ · 4 · │ · · 9 │
└───────┴───────┴───────┘
✅ Solution found in 2352.872ms!
📊 Statistics: 538 propagations, 25 nodes explored
🔍 Efficiency: 21.5 propagations/node
Solution:
┌───────┬───────┬───────┐
│ 9 8 7 │ 6 5 4 │ 3 2 1 │
│ 2 4 6 │ 1 7 3 │ 9 8 5 │
│ 3 5 1 │ 9 2 8 │ 7 4 6 │
├───────┼───────┼───────┤
│ 1 2 8 │ 5 3 7 │ 6 9 4 │
│ 6 3 4 │ 8 9 2 │ 1 5 7 │
│ 7 9 5 │ 4 6 1 │ 8 3 2 │
├───────┼───────┼───────┤
│ 5 1 9 │ 2 8 6 │ 4 7 3 │
│ 4 7 2 │ 3 1 9 │ 5 6 8 │
│ 8 6 3 │ 7 4 5 │ 2 1 9 │
└───────┴───────┴───────┘
──────────────────────────────────────────────────
源代码
//! Simple Sudoku Solver using the specialized SudokuSolver API
//!
//! This example demonstrates solving a 9x9 Sudoku puzzle using the production-ready
//! SudokuSolver that provides a clean API without manual constraint setup.
//! Sudoku rules:
//! 1. Each cell contains a digit 1-9
//! 2. Each row, column, and 3x3 box contains all digits 1-9 exactly once
//!
//! ## Performance Note
//!
//! **Use `cargo run --release --example sudoku` for proper performance benchmarks!**
//! - Release mode: Platinum puzzle ~15 seconds
//! - Debug mode: Platinum puzzle ~118 seconds (7.8x slower)
//!
//! The Platinum puzzle is computationally intensive and requires optimization.
use selen::solvers::SudokuSolver;
fn main() {
println!("🔢 Simple Sudoku Solver");
println!("======================");
// Easy Sudoku puzzle (26 clues)
let easy_puzzle = [
[5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 0, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 0],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 0, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 0],
];
// Hard Sudoku puzzle - "AI Escargot" - known as one of the most difficult
let hard_puzzle = [
[1, 0, 0, 0, 0, 7, 0, 9, 0],
[0, 3, 0, 0, 2, 0, 0, 0, 8],
[0, 0, 9, 6, 0, 0, 5, 0, 0],
[0, 0, 5, 3, 0, 0, 9, 0, 0],
[0, 1, 0, 0, 8, 0, 0, 0, 2],
[6, 0, 0, 0, 0, 4, 0, 0, 0],
[3, 0, 0, 0, 0, 0, 0, 1, 0],
[0, 4, 0, 0, 0, 0, 0, 0, 7],
[0, 0, 7, 0, 0, 0, 3, 0, 0],
];
// Extreme Sudoku puzzle - "World's Hardest Sudoku" - designed to be extremely challenging
let extreme_puzzle = [
[8, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 3, 6, 0, 0, 0, 0, 0],
[0, 7, 0, 0, 9, 0, 2, 0, 0],
[0, 5, 0, 0, 0, 7, 0, 0, 0],
[0, 0, 0, 0, 4, 5, 7, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 3, 0],
[0, 0, 1, 0, 0, 0, 0, 6, 8],
[0, 0, 8, 5, 0, 0, 0, 1, 0],
[0, 9, 0, 0, 0, 0, 4, 0, 0],
];
// "Platinum Blonde" - The ultimate computational challenge
// Now runs in ~14 seconds thanks to architectural improvements (removing dyn-clone dependency)!
let platinum_puzzle = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 3, 0, 8, 5],
[0, 0, 1, 0, 2, 0, 0, 0, 0],
[0, 0, 0, 5, 0, 7, 0, 0, 0],
[0, 0, 4, 0, 0, 0, 1, 0, 0],
[0, 9, 0, 0, 0, 0, 0, 0, 0],
[5, 0, 0, 0, 0, 0, 0, 7, 3],
[0, 0, 2, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 4, 0, 0, 0, 9],
];
// Solve all four puzzles - including Platinum!
let (easy_propagations, easy_nodes) = solve_and_display("EASY", &easy_puzzle);
let (hard_propagations, hard_nodes) = solve_and_display("HARD", &hard_puzzle);
let (extreme_propagations, extreme_nodes) = solve_and_display("EXTREME", &extreme_puzzle);
let (platinum_propagations, platinum_nodes) = solve_and_display("PLATINUM", &platinum_puzzle);
}
fn solve_and_display(difficulty: &str, puzzle: &[[i32; 9]; 9]) -> (usize, usize) {
println!("\n🧩 Solving {} puzzle:", difficulty);
// Create specialized solver
let solver = SudokuSolver::new(*puzzle);
println!("📊 Puzzle stats: {} clues given, {} empty cells", solver.clue_count(), 81 - solver.clue_count());
println!("{}", SudokuSolver::format_grid("Puzzle:", puzzle));
// Solve the puzzle using the specialized solver
let result = solver.solve();
match result.solution {
Some(grid) => {
println!("✅ Solution found in {:.3}ms!", result.duration_ms);
println!("📊 Statistics: {} propagations, {} nodes explored", result.propagations, result.nodes);
// Performance analysis
let efficiency = if result.nodes > 0 {
format!("{:.1} propagations/node", result.propagations as f64 / result.nodes as f64)
} else {
"Pure propagation (no search)".to_string()
};
println!("🔍 Efficiency: {}", efficiency);
if result.pure_propagation {
println!("🎯 Solved by pure constraint propagation!");
}
println!("{}", SudokuSolver::format_grid("Solution:", &grid));
println!("{}", "─".repeat(50));
(result.propagations, result.nodes)
}
None => {
println!("❌ No solution found (took {:.3}ms)", result.duration_ms);
println!("{}", "─".repeat(50));
(0, 0)
}
}
}
从上述源代码可见,它引用了一个专门的数独求解器selen::solvers::SudokuSolver,而这个求解器的开头部分有如下注释
//! Specialized Sudoku solver with optimized constraints and human-solving techniques.
//!
//! This module provides a production-ready Sudoku solver that can be easily used
//! without manual constraint setup. It includes both basic constraint propagation
//! and can be extended with advanced human-solving techniques for better performance.
所以,还是针对数独问题做了优化,不是纯数学推理。
1082

被折叠的 条评论
为什么被折叠?



