Parcourir la source

Adding documentation.

Added AnyBoard flip, flip_x, flip_y.
These will allow me to test row/column processing.
Steve Thielemann il y a 2 semaines
Parent
commit
5ebb0d2b1a
5 fichiers modifiés avec 405 ajouts et 4 suppressions
  1. 4 0
      sudoku/src/bits.rs
  2. 22 0
      sudoku/src/group.rs
  3. 4 0
      sudoku/src/ksudoku.rs
  4. 8 0
      sudoku/src/lib.rs
  5. 367 4
      sudoku/src/sudoku.rs

+ 4 - 0
sudoku/src/bits.rs

@@ -1,3 +1,7 @@
+//! Bits
+//! 
+//! Handles if a certain bit is set. Vec<bool>
+
 use std::ops::RangeBounds;
 use std::fmt;
 // use std::iter::{Map, Filter, Enumerate};

+ 22 - 0
sudoku/src/group.rs

@@ -1,20 +1,42 @@
+//! Sudoku Groups (Rows, Columns, Cells)
+//! 
+//! AnyGroup handles what cells are in each:
+//!   - Row
+//!   - Column
+//!   - Cell
+
 // use std::fmt;
 use strum::EnumIter;
 use strum::IntoEnumIterator;
 // use strum_macros::EnumIter;
 
+/// Groups of significance we track:
+/// 
+/// - Rows
+/// - Columns
+/// - Cells
 #[derive(Debug, EnumIter, PartialEq, Copy, Clone)]
 pub enum Groups {
+    /// Row
     Row,
+    /// Column
     Column,
+    /// Cell
     Cell,
 }
 
+/// AnyGroup
+/// 
+/// This builds the groups for a board of a given size.
 #[derive(Debug, Clone)]
 pub struct AnyGroup {
+    /// Size of the board (3,4,5)
     pub size: u8,
+    /// Width is size*size
     pub width: u8,
+    /// Maximum index value width*width
     pub max_index: usize,
+    /// Groups indexes
     pub groups: [Vec<usize>; 3],
     pub row_cell: Vec<usize>,
     pub col_cell: Vec<usize>,

+ 4 - 0
sudoku/src/ksudoku.rs

@@ -1,3 +1,7 @@
+//! Ksudoku file support
+//! 
+//! This handles saving and loading ksudoku save files.
+
 // Read a Ksudoku's XML save file.
 use std::collections::HashMap;
 use std::error;

+ 8 - 0
sudoku/src/lib.rs

@@ -1,4 +1,12 @@
+// #![deny(missing_docs)]
+#![warn(missing_docs)]
+
+//! Sudoku library
+//! 
+//! This creates new puzzles, as well as solving them.
+
 pub mod group;
+
 pub mod ksudoku;
 pub mod sudoku;
 pub mod bits;

+ 367 - 4
sudoku/src/sudoku.rs

@@ -1,3 +1,11 @@
+//! Sudoku creator and solver.
+//!
+//! This handles boards 9x9, 16x16 and 25x25.
+//!
+//! AnyBoard contains the sudoku board.
+//! AnyPossible tracks possibilities where values can go on the board.
+//! AnySolver solves sudoku AnyBoard.
+
 // pub mod group;
 use crate::bits::*;
 use crate::group::*;
@@ -451,9 +459,51 @@ impl AnyBoard {
         }
         false
     }
+
+    /// Flip board X and Y
+    pub fn flip(&mut self) {
+        let temp = self.clone();
+        for x in 0..self.width {
+            for y in 0..self.width {
+                self[(x, y)] = temp[(y, x)]
+            }
+        }
+    }
+
+    /// Flip board around X
+    pub fn flip_x(&mut self) {
+        let mut temp = vec![0; self.width as usize];
+
+        for y in 0..self.width {
+            for x in 0..self.width {
+                temp[x as usize] = self[(x, y)];
+            }
+            for x in 0..self.width {
+                self[(x, y)] = temp[self.width as usize - 1 - x as usize];
+            }
+        }
+    }
+
+    /// Flip board around Y
+    pub fn flip_y(&mut self) {
+        let mut temp = vec![0; self.width as usize];
+
+        for x in 0..self.width {
+            for y in 0..self.width {
+                temp[y as usize] = self[(x, y)];
+            }
+            for y in 0..self.width {
+                self[(x, y)] = temp[self.width as usize - 1 - y as usize];
+            }
+        }
+    }
 }
 
+//
 // Ok! This is interesting:
+//
+// This allows you to index the board by (u8,u8) or usize.
+//
 
 use std::ops::{Index, IndexMut};
 
@@ -1183,7 +1233,6 @@ impl AnySolver {
                     self.possible.display();
                 }
 
-
                 let cell_start = self.group.cell_start(last_cell_found);
                 let found_x = self.board.xy(col_found).0;
                 if OUTPUT {
@@ -1220,7 +1269,6 @@ impl AnySolver {
                         self.possible.display();
                     }
                 }
-
             }
         }
 
@@ -2682,7 +2730,10 @@ mod tests {
         solver.possible.display();
         println!("Pairs: {:?}", pairs);
         // let expected: Vec<(Vec<usize>, Vec<u8>)> = vec![(vec![0, 1, 2], vec![2, 3, 4])];
-        let expected: Vec<(Vec<usize>, Vec<u8>)> = vec![(vec![3,4,5,6,7,8],vec![0,1,5,6,7,8]),(vec![0, 1, 2], vec![2, 3, 4])];
+        let expected: Vec<(Vec<usize>, Vec<u8>)> = vec![
+            (vec![3, 4, 5, 6, 7, 8], vec![0, 1, 5, 6, 7, 8]),
+            (vec![0, 1, 2], vec![2, 3, 4]),
+        ];
         assert_eq!(pairs.0, expected);
         /*
         (1,1):3,4,5             (2,1):3,4,5             (3,1):3,4,5             (4,1):1,2,6,7,8,9       (5,1):1,2,6,7,8,9       (6,1):1,2,6,7,8,9       (7,1):1,2,6,7,8,9       (8,1):1,2,6,7,8,9       (9,1):1,2,6,7,8,9
@@ -2979,13 +3030,325 @@ mod tests {
         println!("Pairs [cell index 3]: {:?}", pairs);
         // Pairs [cell index 3]: ([([0, 3, 6], [2, 3, 4])], true)
         // [1, 2, 4, 5, 7, 8], [0, 1, 5, 6, 7, 8]
-        let expected: Vec<(Vec<usize>, Vec<u8>)> = vec![(vec![1,2,4,5,7,8],vec![0,1,5,6,7,8]),(vec![0, 3, 6], vec![2, 3, 4])];
+        let expected: Vec<(Vec<usize>, Vec<u8>)> = vec![
+            (vec![1, 2, 4, 5, 7, 8], vec![0, 1, 5, 6, 7, 8]),
+            (vec![0, 3, 6], vec![2, 3, 4]),
+        ];
         assert_eq!(pairs.0, expected);
 
         // solver.finalize_cell(3);
         // solver.possible.display();
     }
 
+    #[test]
+    fn flip_board_test() {
+        let mut base_board = AnyBoard::new(3);
+        let result = base_board.load_from_tld(
+            'b',
+            '_',
+            "__c_____e_h__cb___bd___ei_ch_jb__d___________i_eh__b__dg___ij_f_i__jg_____b_____g",
+        );
+
+        assert!(result.is_ok());
+        // Clone the board here, I want to modify it with flip calls.
+
+        let mut board = base_board.clone();
+        let strings = board.to_strings();
+        assert_eq!(
+            strings,
+            vec![
+                "  17 83  ",
+                " 73   68 ",
+                "2  9 4  1",
+                "   1 7   ",
+                " 2     9 ",
+                " 14   86 ",
+                "  83 19  ",
+                "         ",
+                "4 2   5 6"
+            ]
+        );
+
+        board.display();
+        /*
+        ╔═══╦═══╦═══╗
+        ║  1║7 8║3  ║
+        ║ 73║   ║68 ║
+        ║2  ║9 4║  1║
+        ╠═══╬═══╬═══╣
+        ║   ║1 7║   ║
+        ║ 2 ║   ║ 9 ║
+        ║ 14║   ║86 ║
+        ╠═══╬═══╬═══╣
+        ║  8║3 1║9  ║
+        ║   ║   ║   ║
+        ║4 2║   ║5 6║
+        ╚═══╩═══╩═══╝
+         */
+        let mut solver = AnySolver::new_from(&board);
+        assert!(solver.validate_board());
+
+        solver.reset_possible();
+
+        if !solver.solve_logic() {
+            println!("Failed to solve by logic!");
+            solver.board.display();
+        }
+        solver.board.display();
+
+        /*
+        ╔═══╦═══╦═══╗
+        ║541║768║329║
+        ║973║512║684║
+        ║286║934║751║
+        ╠═══╬═══╬═══╣
+        ║869║157║243║
+        ║325║486║197║
+        ║714║293║865║
+        ╠═══╬═══╬═══╣
+        ║658║341║972║
+        ║197║625║438║
+        ║432║879║516║
+        ╚═══╩═══╩═══╝
+         */
+        assert!(solver.validate_board());
+        assert!(solver.board.complete());
+
+        let strings = solver.board.to_strings();
+        assert_eq!(
+            strings,
+            vec![
+                "541768329",
+                "973512684",
+                "286934751",
+                "869157243",
+                "325486197",
+                "714293865",
+                "658341972",
+                "197625438",
+                "432879516"
+            ]
+        );
+
+        // Reset the board, flip it, and try this again!
+
+        board.copy(&base_board);
+        board.flip();
+        let strings = board.to_strings();
+        board.display();
+        /*
+        ╔═══╦═══╦═══╗
+        ║  2║   ║  4║
+        ║ 7 ║ 21║   ║
+        ║13 ║  4║8 2║
+        ╠═══╬═══╬═══╣
+        ║7 9║1  ║3  ║
+        ║   ║   ║   ║
+        ║8 4║7  ║1  ║
+        ╠═══╬═══╬═══╣
+        ║36 ║  8║9 5║
+        ║ 8 ║ 96║   ║
+        ║  1║   ║  6║
+        ╚═══╩═══╩═══╝
+         */
+        assert_eq!(
+            strings,
+            vec![
+                "  2     4",
+                " 7  21   ",
+                "13   48 2",
+                "7 91  3  ",
+                "         ",
+                "8 47  1  ",
+                "36   89 5",
+                " 8  96   ",
+                "  1     6",
+            ]
+        );
+
+        let mut solver = AnySolver::new_from(&board);
+        assert!(solver.validate_board());
+        solver.reset_possible();
+        if !solver.solve_logic() {
+            println!("Failed to solve by logic!");
+            solver.board.display();
+        }
+        solver.board.display();
+        assert!(solver.validate_board());
+        assert!(solver.board.complete());
+
+        let strings = solver.board.to_strings();
+        assert_eq!(
+            strings,
+            vec![
+                "592837614",
+                "478621593",
+                "136954872",
+                "759142368",
+                "613589427",
+                "824763159",
+                "367218945",
+                "285496731",
+                "941375286",
+            ]
+        );
+
+        // Reset the board, flip it, and try this again!
+
+        board.copy(&base_board);
+        board.flip_x();
+        let strings = board.to_strings();
+        board.display();
+        /*
+        ╔═══╦═══╦═══╗
+        ║  3║8 7║1  ║
+        ║ 86║   ║37 ║
+        ║1  ║4 9║  2║
+        ╠═══╬═══╬═══╣
+        ║   ║7 1║   ║
+        ║ 9 ║   ║ 2 ║
+        ║ 68║   ║41 ║
+        ╠═══╬═══╬═══╣
+        ║  9║1 3║8  ║
+        ║   ║   ║   ║
+        ║6 5║   ║2 4║
+        ╚═══╩═══╩═══╝
+         */
+        assert_eq!(
+            strings,
+            vec![
+                "  38 71  ",
+                " 86   37 ",
+                "1  4 9  2",
+                "   7 1   ",
+                " 9     2 ",
+                " 68   41 ",
+                "  91 38  ",
+                "         ",
+                "6 5   2 4",
+            ]
+        );
+
+        let mut solver = AnySolver::new_from(&board);
+        assert!(solver.validate_board());
+        solver.reset_possible();
+        if !solver.solve_logic() {
+            println!("Failed to solve by logic!");
+            solver.board.display();
+        }
+        solver.board.display();
+        /*
+        ╔═══╦═══╦═══╗
+        ║923║867║145║
+        ║486║215║379║
+        ║157║439║682║
+        ╠═══╬═══╬═══╣
+        ║342║751║968║
+        ║791║684║523║
+        ║568║392║417║
+        ╠═══╬═══╬═══╣
+        ║279║143║856║
+        ║834║526║791║
+        ║615║978║234║
+        ╚═══╩═══╩═══╝
+         */
+        assert!(solver.validate_board());
+        assert!(solver.board.complete());
+
+        let strings = solver.board.to_strings();
+        assert_eq!(
+            strings,
+            vec![
+                "923867145",
+                "486215379",
+                "157439682",
+                "342751968",
+                "791684523",
+                "568392417",
+                "279143856",
+                "834526791",
+                "615978234",
+            ]
+        );
+        // Reset the board, flip it, and try this again!
+
+        board.copy(&base_board);
+        board.flip_y();
+        let strings = board.to_strings();
+        board.display();
+        /*
+        ╔═══╦═══╦═══╗
+        ║4 2║   ║5 6║
+        ║   ║   ║   ║
+        ║  8║3 1║9  ║
+        ╠═══╬═══╬═══╣
+        ║ 14║   ║86 ║
+        ║ 2 ║   ║ 9 ║
+        ║   ║1 7║   ║
+        ╠═══╬═══╬═══╣
+        ║2  ║9 4║  1║
+        ║ 73║   ║68 ║
+        ║  1║7 8║3  ║
+        ╚═══╩═══╩═══╝
+         */
+        assert_eq!(
+            strings,
+            vec![
+                "4 2   5 6",
+                "         ",
+                "  83 19  ",
+                " 14   86 ",
+                " 2     9 ",
+                "   1 7   ",
+                "2  9 4  1",
+                " 73   68 ",
+                "  17 83  ",
+            ]
+        );
+
+        let mut solver = AnySolver::new_from(&board);
+        assert!(solver.validate_board());
+        solver.reset_possible();
+        if !solver.solve_logic() {
+            println!("Failed to solve by logic!");
+            solver.board.display();
+        }
+        solver.board.display();
+        /*
+        ╔═══╦═══╦═══╗
+        ║432║879║516║
+        ║197║625║438║
+        ║658║341║972║
+        ╠═══╬═══╬═══╣
+        ║714║293║865║
+        ║325║486║197║
+        ║869║157║243║
+        ╠═══╬═══╬═══╣
+        ║286║934║751║
+        ║973║512║684║
+        ║541║768║329║
+        ╚═══╩═══╩═══╝
+         */
+        assert!(solver.validate_board());
+        assert!(solver.board.complete());
+
+        let strings = solver.board.to_strings();
+        assert_eq!(
+            strings,
+            vec![
+                "432879516",
+                "197625438",
+                "658341972",
+                "714293865",
+                "325486197",
+                "869157243",
+                "286934751",
+                "973512684",
+                "541768329",
+            ]
+        );
+    }
+
     /*
     10/13/2024
     This assumes the solver is working correctly.