ソースを参照

Tests working again.

I commented out the extra check in process_move.
Use ./test=out --ignored to view logic tests.
The logic tests describe what I'm trying to do here.
I haven't quite figured out how to do it just yet.
Steve Thielemann 3 ヶ月 前
コミット
eebe4ee636
4 ファイル変更435 行追加10 行削除
  1. 2 0
      src/main.rs
  2. 15 4
      sudoku/src/group.rs
  3. 415 6
      sudoku/src/sudoku.rs
  4. 3 0
      test-out

+ 2 - 0
src/main.rs

@@ -41,6 +41,8 @@ fn main() {
         let mut solution = AnySolver::new(size);
 
         solution.make();
+        solution.board.display();
+        // 16x16 make_puzzle() takes too long.
         let mut puzzle = solution.clone();
         for _ in 0..81 {
             puzzle.make_puzzle();

+ 15 - 4
sudoku/src/group.rs

@@ -112,6 +112,14 @@ impl AnyGroup {
         (x / self.size) + (y / self.size) * self.size
     }
 
+    /// Return index of cell (x,y)
+    /// - This uses the groups to locate the index of the group.
+    pub fn cell_index(&self, index: u8, x: u8, y: u8) -> usize {
+        let result: usize =
+            self.groups[Groups::Cell as usize][index as usize * self.width as usize];
+        result + (y * self.width + x) as usize
+    }
+
     pub fn calculate(&mut self) {
         for y in 0..self.width {
             for x in 0..self.width {
@@ -238,8 +246,6 @@ mod tests {
     /// Verify that each index (0..max_index) is defined in each group.
     /// - Verify that it is used, and only once.
     fn check_dynamic() {
-
-
         for size in 3..=5 {
             let g = AnyGroup::new(size);
             // g.display();
@@ -290,10 +296,9 @@ mod tests {
                         y + 1
                     );
                 }
-    
             }
 
-            /* 
+            /*
             all.fill(0);
             for idx in 0..g.width {
                 let grp = g.row(idx);
@@ -357,4 +362,10 @@ mod tests {
             */
         }
     }
+    #[test]
+    fn check_cells() {
+        let size = 3;
+        let g = AnyGroup::new(size);
+        assert_eq!(g.cell_index(0, 0, 0), 0);
+    }
 }

+ 415 - 6
sudoku/src/sudoku.rs

@@ -588,15 +588,21 @@ pub struct AnySolver {
     pub board: AnyBoard,
     pub possible: AnyPossible,
     pub group: AnyGroup,
+    pub cell_poss: Vec<GenBits<u32>>,
 }
 
 impl AnySolver {
     /// Construct new solver from given board size. (3,4,5)
     pub fn new(board_size: u8) -> Self {
+        let mut default_poss = GenBits::<u32>(0);
+        let width: u8 = board_size * board_size;
+        default_poss.set_bits(0..width);
+
         let mut s = Self {
             board: AnyBoard::new(board_size),
             possible: AnyPossible::new(board_size),
             group: AnyGroup::new(board_size),
+            cell_poss: vec![default_poss; width as usize * width as usize],
         };
         s.reset_possible();
         s
@@ -604,10 +610,17 @@ impl AnySolver {
 
     /// Construct new solver from given board.
     pub fn new_from(initial_board: &AnyBoard) -> Self {
+        let mut default_poss = GenBits::<u32>(0);
+        default_poss.set_bits(0..initial_board.width);
+
         let mut s = AnySolver {
             board: initial_board.clone(),
             possible: AnyPossible::new(initial_board.size),
             group: AnyGroup::new(initial_board.size),
+            cell_poss: vec![
+                default_poss;
+                initial_board.width as usize * initial_board.width as usize
+            ],
         };
         s.reset_possible();
         s
@@ -625,6 +638,8 @@ impl AnySolver {
     /// Process a move
     /// - Remove value from rows, columns, and cells.
     /// - Clear possibles from (x,y) position, it's filled.
+    /// - **THIS PANICS** debug_assert!, panics in test validated_board
+    /// TO FIX: This needs to return an error. (someway, somehow)
     pub fn process_move(&mut self, x: u8, y: u8, value: u8) {
         debug_assert!(
             x <= self.board.width && y <= self.board.width,
@@ -654,8 +669,84 @@ impl AnySolver {
             self.possible.set(*g, val, false);
         }
         let idx = self.possible.pos(x, y);
-        self.possible.possible[idx] = GenBits::<u32>(0); // .clear();
+        self.possible.possible[idx] = GenBits::<u32>(0);
         self.board.board[idx] = value;
+
+        //
+        // When working with GenBits, remember to use value -1
+        //
+
+        /*
+        let ok = self.cell_poss[cell_index as usize].get(value as usize-1);
+        if !ok {
+            println!("{:?}", self.cell_poss);
+            println!("Cell {} ({},{})={}", cell_index, x, y, value);
+        }
+        */
+
+        // Tests are run as debug, and this kills things...
+        // Like the invalid board in validated_board test.
+        let cell_index = self.group.which_cell(x, y);
+
+        /*
+        Never use this code.  It asserts/panics on invalid boards.
+        (Which is what validate_board checks...)
+
+        debug_assert!(
+            self.cell_poss[cell_index as usize].get(value as usize - 1),
+            "Cell {} ({},{})={}",
+            cell_index,
+            x,
+            y,
+            value
+        );
+        */
+        self.cell_poss[cell_index as usize].set(value as usize - 1, false);
+
+        self.finalize_cell(cell_index);
+
+        // Should I do the checks here for the logic possible fix?
+        // Or, should I make it a different function?
+        // Put somewhere else, since it has to re-check the entire board!
+
+        // OR, just check row and columns?
+    }
+
+    /// Finalize move on the board.
+    /// - This uses the cell index last modified, so we have fewer
+    ///   cells to check here. (2 * size) cells.
+    pub fn finalize_cell(&mut self, index:u8) {
+        let size = self.board.size;
+
+        // Check columns
+        for c in 0..size {
+            // Calculate the row and column for the given cell.
+            let _col = (index % size)*size + c;
+            // println!("Index {} COL {}", index, col);
+        }
+
+        // Check rows
+        for r in 0..size {
+            // Calculate the row and column for the given cell.
+            let _row = (index / size) * size + r;
+            // println!("Index {} ROW {}", index, row);
+        }
+
+    }
+
+    /// Finalize move(s) on the board.
+    /// - This checks the board for logic fixes. (when column is full/has 1+pair/triple)
+    pub fn finalize_move(&mut self) {
+        for idx in 0..3 {
+            let mut _ix: u8 = idx * 3;
+            let mut _iy: u8 = idx * 3;
+
+            println!("Index {} x {} y {}", idx, _ix, _iy);
+            // Check cell rows
+            
+            // Check cell columns
+        }
+        assert!(false, "Boing!");
     }
 
     /// Validate the board
@@ -666,6 +757,14 @@ impl AnySolver {
         let mut has_blanks = false;
 
         self.possible.clear();
+        // reset cell possible
+        let mut default_poss = GenBits::<u32>(0);
+        default_poss.set_bits(0..self.board.width);
+
+        for x in 0..self.board.width {
+            self.cell_poss[x as usize] = default_poss;
+        }
+
         for y in 0..self.board.width {
             for x in 0..self.board.width {
                 let value = self.board.get(x, y);
@@ -714,6 +813,15 @@ impl AnySolver {
     /// - When something has changed, and the possibles are out of sync.
     pub fn reset_possible(&mut self) {
         self.possible.clear();
+
+        // reset cell possible
+        let mut default_poss = GenBits::<u32>(0);
+        default_poss.set_bits(0..self.board.width);
+
+        for x in 0..self.board.width {
+            self.cell_poss[x as usize] = default_poss;
+        }
+
         for y in 0..self.board.width {
             for x in 0..self.board.width {
                 let value = self.board.get(x, y);
@@ -807,6 +915,11 @@ impl AnySolver {
                     // Failure
                     self.board.copy(&backup.board);
                     self.possible.copy(&backup.possible);
+
+                    for i in 0..backup.cell_poss.len() {
+                        self.cell_poss[i] = backup.cell_poss[i];
+                    }
+                    // self.cell_poss.copy( backup.cell_poss);
                 }
 
                 // We've run out of possible.
@@ -1351,6 +1464,120 @@ impl AnySolver {
 mod tests {
     use crate::sudoku::*;
 
+    #[ignore]
+    #[test]
+    fn logic_test() {
+        let mut board = AnyBoard::new(3);
+        board.set(1, 0, 2);
+        board.set(0, 3, 3);
+        board.set(0, 4, 4);
+        board.set(0, 5, 5);
+        board.display();
+        let mut solver = AnySolver::new_from(&board);
+        /*
+           ╔═══╦═══╦═══╗
+           ║ 2 ║   ║   ║
+           ║   ║   ║   ║
+           ║   ║   ║   ║
+           ╠═══╬═══╬═══╣
+           ║3  ║   ║   ║
+           ║4  ║   ║   ║
+           ║5  ║   ║   ║
+           ╠═══╬═══╬═══╣
+           ║   ║   ║   ║
+           ║   ║   ║   ║
+           ║   ║   ║   ║
+           ╚═══╩═══╩═══╝
+           (1,1):1,6,7,8,9         (2,1):                  (3,1):1,3,4,5,6,7,8,9
+           (1,2):1,6,7,8,9         (2,2):1,3,4,5,6,7,8,9   (3,2):1,3,4,5,6,7,8,9
+           (1,3):1,6,7,8,9         (2,3):1,3,4,5,6,7,8,9   (3,3):1,3,4,5,6,7,8,9
+           (1,4):                  (2,4):1,6,7,8,9         (3,4):1,2,6,7,8,9
+           (1,5):                  (2,5):1,6,7,8,9         (3,5):1,2,6,7,8,9
+           (1,6):                  (2,6):1,6,7,8,9         (3,6):1,2,6,7,8,9
+           (1,7):1,2,6,7,8,9       (2,7):1,3,4,5,6,7,8,9   (3,7):1,2,3,4,5,6,7,8,9
+           (1,8):1,2,6,7,8,9       (2,8):1,3,4,5,6,7,8,9   (3,8):1,2,3,4,5,6,7,8,9
+           (1,9):1,2,6,7,8,9       (2,9):1,3,4,5,6,7,8,9   (3,9):1,2,3,4,5,6,7,8,9
+           ^ This shows the logic bug.
+           (3,7), (3,8) and (3,9) should not contain 2!
+
+        */
+
+        assert!(solver.validate_board());
+        solver.possible.display();
+
+        /*
+        // Validate the broken possible board.
+        for i in 3..9 {
+            assert!(!solver.possible.get(solver.possible.pos(1, i), 2), "Possible ({},{}) does not have 2", 1+1, i+1);
+            assert!(solver.possible.get(solver.possible.pos(2, i), 2), "Possible ({},{}) does have 2", 2+1, i+1);
+            if i > 6 {
+                assert!(solver.possible.get(solver.possible.pos(0, i), 2), "Possible ({},{}) does have 2", 0+1, i+1);
+            }
+        }
+        */
+        for i in 6..9 {
+            assert!(
+                !solver.possible.get(solver.possible.pos(2, i), 2),
+                "Possible ({},{}) can not contain 2.",
+                2 + 1,
+                i + 1
+            );
+        }
+
+        // Test 2 - pairs
+
+        // let p = solver.possible.get(solver.possible.pos(2,4), 2);
+
+        println!("--- logic_test ---");
+    }
+
+    #[ignore]    
+    #[test]
+    fn logic_test_pairs() {
+        let mut board = AnyBoard::new(3);
+        board.set(1, 0, 2);
+        board.set(2, 1, 3);
+        board.set(2,2, 5);
+        board.set(1, 6, 3);
+        board.set(0, 4, 4);
+        board.set(1, 7, 5);
+        board.display();
+        let mut solver = AnySolver::new_from(&board);
+        /*
+           ╔═══╦═══╦═══╗
+           ║ 2 ║   ║   ║
+           ║  3║   ║   ║
+           ║  5║   ║   ║
+           ╠═══╬═══╬═══╣
+           ║P  ║   ║   ║
+           ║4  ║   ║   ║
+           ║P  ║   ║   ║
+           ╠═══╬═══╬═══╣
+           ║ 3 ║   ║   ║
+           ║ 5 ║   ║   ║
+           ║   ║   ║   ║
+           ╚═══╩═══╩═══╝
+           P = Possible pair (3,5)
+
+           (1,1):1,6,7,8,9         (2,1):                  (3,1):1,3,4,5,6,7,8,9
+           (1,2):1,6,7,8,9         (2,2):1,3,4,5,6,7,8,9   (3,2):1,3,4,5,6,7,8,9
+           (1,3):1,6,7,8,9         (2,3):1,3,4,5,6,7,8,9   (3,3):1,3,4,5,6,7,8,9
+           (1,4):                  (2,4):1,6,7,8,9         (3,4):1,2,6,7,8,9
+           (1,5):                  (2,5):1,6,7,8,9         (3,5):1,2,6,7,8,9
+           (1,6):                  (2,6):1,6,7,8,9         (3,6):1,2,6,7,8,9
+           (1,7):1,2,6,7,8,9       (2,7):1,3,4,5,6,7,8,9   (3,7):1,2,3,4,5,6,7,8,9
+           (1,8):1,2,6,7,8,9       (2,8):1,3,4,5,6,7,8,9   (3,8):1,2,3,4,5,6,7,8,9
+           (1,9):1,2,6,7,8,9       (2,9):1,3,4,5,6,7,8,9   (3,9):1,2,3,4,5,6,7,8,9
+           ^ This shows the logic bug.
+           (3,7), (3,8) and (3,9) should not contain 2!
+
+        */
+
+        assert!(solver.validate_board());
+        solver.possible.display();
+
+    }
+
     #[test]
     fn display_board() {
         let mut board = AnyBoard::new(3);
@@ -1382,13 +1609,44 @@ mod tests {
 
         solver.reset_possible();
 
-        if solver.solve_logic() {
+        if !solver.solve_logic() {
             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"
+            ]
+        );
+
         board = AnyBoard::new(4);
         let result = board.load_from_tld('b', '_', "_bo_j_m_f__dp__ge_h_pcfdo___q__n___qio______df___f__l___hpnm_i___obig_p_qhl__k_m_dq_cn______o_g_p_____bi_kc__jn______fo____gi______eb____jd______jk__ml_bn_____i_m_b______oq_nj_d_n__jck_m_fgbq___i_medp___n__b___dg______qjk___j__p___fgohl_d_qo__mq__g_d_p_le_");
         assert!(result.is_ok());
@@ -1418,15 +1676,58 @@ mod tests {
 
         let mut solver = AnySolver::new_from(&board);
         assert!(solver.validate_board());
-        solver.board.display();
 
-        if solver.solve_logic() {
+        if !solver.solve_logic() {
             solver.board.display();
         }
-
-        assert!(solver.validate_board());
+        /*
         solver.board.display();
+        ╔════╦════╦════╦════╗
+        ║HDLJ║MKOB║FPEC║GAIN║
+        ║AKOE║NCFD║GILH║PMBJ║
+        ║NGFB║APLI║OJKM║HCDE║
+        ║MIPC║HJEG║DBAN║KFOL║
+        ╠════╬════╬════╬════╣
+        ║IOHK║FBDJ║AECG║LNMP║
+        ║JBNF║CMPE║HLOI║DKAG║
+        ║LEMD║OGAN║PKFB║CHJI║
+        ║GCAP║ILHK║MNDJ║OBEF║
+        ╠════╬════╬════╬════╣
+        ║ENIG║POCM║KABD║JLFH║
+        ║PFKO║GEJA║IMHL║BDNC║
+        ║DHJM║KIBL║CFNO║EPGA║
+        ║CABL║DHNF║JGPE║MIKO║
+        ╠════╬════╬════╬════╣
+        ║OPCA║ENKH║BDGF║IJLM║
+        ║BLEH║JDIP║NOMA║FGCK║
+        ║KJGN║BFMO║LCIP║AEHD║
+        ║FMDI║LAGC║EHJK║NOPB║
+        ╚════╩════╩════╩════╝
+        */
+        assert!(solver.validate_board());
         assert!(solver.board.complete());
+        let strings: Vec<String> = solver.board.to_strings();
+        assert_eq!(
+            strings,
+            vec![
+                "HDLJMKOBFPECGAIN",
+                "AKOENCFDGILHPMBJ",
+                "NGFBAPLIOJKMHCDE",
+                "MIPCHJEGDBANKFOL",
+                "IOHKFBDJAECGLNMP",
+                "JBNFCMPEHLOIDKAG",
+                "LEMDOGANPKFBCHJI",
+                "GCAPILHKMNDJOBEF",
+                "ENIGPOCMKABDJLFH",
+                "PFKOGEJAIMHLBDNC",
+                "DHJMKIBLCFNOEPGA",
+                "CABLDHNFJGPEMIKO",
+                "OPCAENKHBDGFIJLM",
+                "BLEHJDIPNOMAFGCK",
+                "KJGNBFMOLCIPAEHD",
+                "FMDILAGCEHJKNOPB"
+            ]
+        );
 
         let mut board: AnyBoard = AnyBoard::new(5);
         let result = board.load_from_tld('b', '_', "_m_kzg____h_s_n____ftd_u_u_dh_____f_b_t_w_____yg_c_rl_o_tdhy__m__uvig_w_sk_eg___p_q_jikouys_r_d___mlq_t_sb_emcwg_dlzyo_kp_i_ng__ir_b_fp_vhz_ce_y_jm__w__m__o_k_xul_qbt_d_s__e____otv_dhegn___mfkpz_blr____s_dv_n_mjx_ckg_w_bo_p___kqyelwjcz_____nxumoisdh_z__fp_vbi_______dkx_eg__r_y_mlwf_u__q_i__o_chdv_j_i_he_r_____________p_zl_k_d_vbjh_y__e_p__s_tguc_q_s__qj_kpn_______ufw_hx__i_hvntirfxw_____lbckympjg___u_kz_m_bfn_yvx_h_ir_o____rgm_otlnx___ipfes_kwc____p__c_v_ugh_krj_m_w__x__x__ci_j_qk_mpo_dr_u_zb__ht_i_qe_wjvcy_bhkzx_ng_u_syv___u_c_hsfrlqo_t_e___pj_cn_h_slzr__j__mqgp_y_vd_m_bs_____t_o_n_h_____ez_f_e_ufd____p_g_z____cqr_x_");
@@ -1465,6 +1766,79 @@ mod tests {
         );
         let mut solver = AnySolver::new_from(&board);
         assert!(solver.validate_board());
+
+        // This takes awhile to solve...
+        if !solver.solve_logic() {
+            solver.board.display();
+        }
+        assert!(solver.validate_board());
+        assert!(solver.board.complete());
+
+        /*
+        solver.board.display();
+        ╔═════╦═════╦═════╦═════╦═════╗
+        ║UTODP║FIBGA║YMHQR║NKCEW║SXJLV║
+        ║LHQFI║MYTEJ║SXWCN║GVPAR║OUBKD║
+        ║XCKES║WLNRP║VFGJB║UTQOD║HYMAI║
+        ║JGAVW║HOSKX║ELDUP║MIFYB║QCNRT║
+        ║YMNBR║QVUCD║OKTAI║SJLXH║PWGFE║
+        ╠═════╬═════╬═════╬═════╬═════╣
+        ║FJMOA║RNPUK║LVQIS║HYGBX║DTEWC║
+        ║KWSYT║AHCXV║UEBGJ║QONDI║LFRPM║
+        ║QRCPD║TJGMI║AYNWO║ELSUF║VBKHX║
+        ║VNGUL║EQDSB║HTFXM║WCKRP║IAYOJ║
+        ║HEXIB║OWFLY║RDPKC║VAMTJ║UGQSN║
+        ╠═════╬═════╬═════╬═════╬═════╣
+        ║GQPHV║CTMIS║XJANL║YEWFK║BRDUO║
+        ║OABJF║UKVWQ║IPCDY║RMTGL║XESNH║
+        ║RYLNU║GXHDE║TWVMK║PBASO║CQIJF║
+        ║WSETC║YPRBF║GHUOQ║DXIJN║AKVML║
+        ║MIDXK║NALJO║BRSEF║CUHQV║GPWTY║
+        ╠═════╬═════╬═════╬═════╬═════╣
+        ║AVTRY║BSEFM║PQXHD║KWOIC║JNLGU║
+        ║BOUSX║DGJHW║CNLRT║AFEMQ║YVPIK║
+        ║IPHQN║KCOVT║JAMYE║BGDLU║WSFXR║
+        ║DKFMG║XUYQL║WBISV║JPRNT║EHOCA║
+        ║ELWCJ║PRIAN║KGOFU║XHYVS║MDTQB║
+        ╠═════╬═════╬═════╬═════╬═════╣
+        ║SUVWO║IEANH║DCRTG║LQJKY║FMXBP║
+        ║CXIGE║LMKTR║FUYBW║OSVPA║NJHDQ║
+        ║PFRAH║JDQOC║MSKVX║INBWE║TLUYG║
+        ║TDJLQ║SBXYG║NIEPA║FRUHM║KOCVW║
+        ║NBYKM║VFWPU║QOJLH║TDXCG║RIAES║
+        ╚═════╩═════╩═════╩═════╩═════╝
+         */
+        let strings: Vec<String> = solver.board.to_strings();
+        assert_eq!(
+            strings,
+            vec![
+                "UTODPFIBGAYMHQRNKCEWSXJLV",
+                "LHQFIMYTEJSXWCNGVPAROUBKD",
+                "XCKESWLNRPVFGJBUTQODHYMAI",
+                "JGAVWHOSKXELDUPMIFYBQCNRT",
+                "YMNBRQVUCDOKTAISJLXHPWGFE",
+                "FJMOARNPUKLVQISHYGBXDTEWC",
+                "KWSYTAHCXVUEBGJQONDILFRPM",
+                "QRCPDTJGMIAYNWOELSUFVBKHX",
+                "VNGULEQDSBHTFXMWCKRPIAYOJ",
+                "HEXIBOWFLYRDPKCVAMTJUGQSN",
+                "GQPHVCTMISXJANLYEWFKBRDUO",
+                "OABJFUKVWQIPCDYRMTGLXESNH",
+                "RYLNUGXHDETWVMKPBASOCQIJF",
+                "WSETCYPRBFGHUOQDXIJNAKVML",
+                "MIDXKNALJOBRSEFCUHQVGPWTY",
+                "AVTRYBSEFMPQXHDKWOICJNLGU",
+                "BOUSXDGJHWCNLRTAFEMQYVPIK",
+                "IPHQNKCOVTJAMYEBGDLUWSFXR",
+                "DKFMGXUYQLWBISVJPRNTEHOCA",
+                "ELWCJPRIANKGOFUXHYVSMDTQB",
+                "SUVWOIEANHDCRTGLQJKYFMXBP",
+                "CXIGELMKTRFUYBWOSVPANJHDQ",
+                "PFRAHJDQOCMSKVXINBWETLUYG",
+                "TDJLQSBXYGNIEPAFRUHMKOCVW",
+                "NBYKMVFWPUQOJLHTDXCGRIAES"
+            ]
+        );
     }
 
     #[test]
@@ -1557,7 +1931,23 @@ mod tests {
         board.set(0, 8, 7);
         board.set(1, 8, 8);
         board.set(2, 8, 9);
+        /*
         // board.display();
+        ╔═══╦═══╦═══╗
+        ║   ║ 1 ║   ║
+        ║   ║ 2 ║   ║
+        ║   ║ 3 ║   ║
+        ╠═══╬═══╬═══╣
+        ║   ║ 4 ║   ║
+        ║   ║ 5 ║   ║
+        ║   ║ 6 ║   ║
+        ╠═══╬═══╬═══╣
+        ║   ║   ║   ║
+        ║   ║   ║   ║
+        ║789║ ! ║   ║
+        ╚═══╩═══╩═══╝
+        The ! can't possibly be anything.
+         */
 
         let mut solver = AnySolver::new_from(&board);
         assert!(!solver.validate_board());
@@ -1566,9 +1956,28 @@ mod tests {
         let mut board = AnyBoard::new(3);
         board.set(4, 0, 1);
         board.set(4, 1, 1);
+        /*
         // board.display();
+        ╔═══╦═══╦═══╗
+        ║   ║ 1 ║   ║
+        ║   ║ 1 ║   ║
+        ║   ║   ║   ║
+        ╠═══╬═══╬═══╣
+        ║   ║   ║   ║
+        ║   ║   ║   ║
+        ║   ║   ║   ║
+        ╠═══╬═══╬═══╣
+        ║   ║   ║   ║
+        ║   ║   ║   ║
+        ║   ║   ║   ║
+        ╚═══╩═══╩═══╝
+        */
+
+        // Because of the new AnySolver.process_move code --
+        // This panics (as would validate_board!)
 
         let mut solver = AnySolver::new_from(&board);
+
         assert!(!solver.validate_board());
 
         // Invalid board: Has two 1's in same row & cell.

+ 3 - 0
test-out

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+cargo test -p sudoku -- --show-output $*