Programmieren in Rust

Beispiele: Sudoku-Löser

// Erschöpfende Suche mittels Backtracking-Verfahren.
// Listet sämtliche Lösungen eines Sudokus auf.

struct Sudoku {
    data: [[u32; 9]; 9]
}

impl std::fmt::Display for Sudoku {
    fn fmt(&self, f: &mut std::fmt::Formatter)
    -> std::fmt::Result
    {
        for (i, row) in self.data.iter().enumerate() {
            if i != 0 && i%3 == 0 {
                writeln!(f, "------+-------+------")?;
            }
            for (j, cell) in row.iter().enumerate() {
                if j != 0 {
                    write!(f, "{}",
                        if j%3 == 0 {" | "} else {" "})?;
                }
                write!(f, "{}", cell)?;
            }
            writeln!(f)?;
        }
        Ok(())
    }
}

impl Sudoku {
    fn from_input(s: &str) -> Self {
        let mut data = [[0; 9]; 9];
        let mut i = 0;
        let mut j = 0;
        for c in s.chars() {
            if let Some(digit) = c.to_digit(10) {
                data[i][j] = digit;
                j += 1;
            } else if c == '.' {
                data[i][j] = 0;
                j += 1;
            }
            if j == 9 {j = 0; i += 1;}
        }
        Self {data}
    }
    fn unique(&self, digit: u32, i: usize, j: usize) -> bool {
        for k in 0..9 {
            if digit == self.data[k][j] {return false;}
            if digit == self.data[i][k] {return false;}
        }
        let i = (i/3)*3;
        let j = (j/3)*3;
        for x in 0..3 {
            for y in 0..3 {
                if digit == self.data[i+x][j+y] {return false;}
            }
        }
        true
    }
}

fn solve(s: &mut Sudoku, callback: &mut dyn FnMut(&Sudoku)) {
    for i in 0..9 {
        for j in 0..9 {
            if s.data[i][j] == 0 {
                for digit in 1..10 {
                    if s.unique(digit, i, j) {
                        s.data[i][j] = digit;
                        solve(s, callback);
                        s.data[i][j] = 0;
                    }
                }
                return;
            }
        }
    }
    callback(s);
}

static S1: &str = "
. . 3 | . . 9 | 6 . .
4 . . | . . 2 | . . 3
8 6 2 | 1 5 3 | . 9 .
------+-------+------
5 . 7 | 2 . 6 | . 3 .
. 3 . | 5 . . | . . .
6 . 9 | . 7 . | . 5 1
------+-------+------
. 2 . | 4 . 8 | . . 7
. 4 . | . 3 . | . 2 .
3 . . | . 2 5 | 1 4 8
";

static S2: &str = "
9 . . | . . . | . . .
. . . | . . 1 | . . 7
5 . . | . . 3 | . . 4
------+-------+------
. . 7 | . . . | 2 . .
. . 3 | 6 . 8 | . . .
. . . | 4 . . | 6 1 .
------+-------+------
. 8 5 | . 4 . | . . .
. . . | 3 2 . | . 6 .
. 4 . | . 1 . | . 9 .
";

fn solve_sudoku(input: &str) {
    let s = &mut Sudoku::from_input(input);
    let mut count = 0;
    solve(s, &mut |solution| {
        count += 1;
        println!("Lösung Nr. {}", count);
        println!("{}", solution);
    });
}

fn main() {
    solve_sudoku(S1);
    solve_sudoku(S2);
}