use optimization_tools::*; use sudoku::*; use test_tools::prelude::*; use deterministic_rand::Hrng; // #[ macro_export ] // macro_rules! cells_container // { // ( $( $Tokens : tt )+ ) => // {{ // [ $( $Tokens )+ ].into_iter().map( | e | e.into() ).collect() // }} // } // zzz : move to iter_tools, maybe fn each_into< T, IntoIter, IntoCellVal >( src : IntoIter ) -> impl Iterator< Item = T > where IntoIter : IntoIterator< Item = IntoCellVal >, IntoCellVal : Into< T >, { src.into_iter().map( | e | e.into() ) } #[ test ] fn from_string() { let src = " 310 000 020 006 109 005 000 080 000 020 804 050 004 070 000 000 060 008 060 000 900 009 405 001 000 007 000 "; let got : Board = src.into(); let storage : Vec< CellVal > = each_into ([ 3,1,0, 0,0,0, 0,2,0, 0,0,6, 1,0,9, 0,0,5, 0,0,0, 0,8,0, 0,0,0, 0,2,0, 8,0,4, 0,5,0, 0,0,4, 0,7,0, 0,0,0, 0,0,0, 0,6,0, 0,0,8, 0,6,0, 0,0,0, 9,0,0, 0,0,9, 4,0,5, 0,0,1, 0,0,0, 0,0,7, 0,0,0, ]).collect(); let exp = Board::new( storage ); a_id!( got, exp ); } #[ test ] fn cell() { let board = Board::default(); let mut cells = board.cells(); assert_eq!( ( CellIndex::from( ( 0, 0 ) ), CellVal::from( 3 ) ), cells.next().unwrap() ); assert_eq!( ( CellIndex::from( ( 1, 0 ) ), CellVal::from( 1 ) ), cells.next().unwrap() ); assert_eq!( ( CellIndex::from( ( 2, 0 ) ), CellVal::from( 0 ) ), cells.next().unwrap() ); cells.next(); cells.next(); cells.next(); cells.next(); cells.next(); cells.next(); cells.next(); cells.next(); cells.next(); assert_eq!( ( CellIndex::from( ( 3, 1 ) ), CellVal::from( 1 ) ), cells.next().unwrap() ); assert_eq!( ( CellIndex::from( ( 4, 1 ) ), CellVal::from( 0 ) ), cells.next().unwrap() ); assert_eq!( ( CellIndex::from( ( 5, 1 ) ), CellVal::from( 9 ) ), cells.next().unwrap() ); } #[ test ] fn col() { let board = Board::default(); let exp : Vec< CellVal > = each_into([ 3, 0, 0, 0, 0, 0, 0, 0, 0 ]).collect(); let got = board.col( 0 ).collect::< Vec< _ > >(); a_id!( got, exp ); let exp : Vec< CellVal > = each_into([ 0, 5, 0, 0, 0, 8, 0, 1, 0 ]).collect(); let got = board.col( 8 ).collect::< Vec< _ > >(); a_id!( got, exp ); a_id!( board.cols().count(), 9 ); } #[ test ] fn row() { let board = Board::default(); let exp : Vec< CellVal > = each_into([ 3, 1, 0, 0, 0, 0, 0, 2, 0 ]).collect(); let got = board.row( 0 ).collect::< Vec< _ > >(); a_id!( got, exp ); let exp : Vec< CellVal > = each_into([ 0, 0, 0, 0, 0, 7, 0, 0, 0 ]).collect(); let got = board.row( 8 ).collect::< Vec< _ > >(); a_id!( got, exp ); a_id!( board.rows().count(), 9 ); } #[ test ] fn block() { let board = Board::default(); let got = board.block( ( 0, 0 ).into() ).collect::< Vec< _ > >(); let exp : Vec< CellVal > = each_into([ 3, 1, 0, 0, 0, 6, 0, 0, 0 ]).collect(); a_id!( got, exp ); let got = board.block( ( 1, 0 ).into() ).collect::< Vec< _ > >(); let exp : Vec< CellVal > = each_into([ 0, 0, 0, 1, 0, 9, 0, 8, 0 ]).collect(); a_id!( got, exp ); let got = board.block( ( 2, 2 ).into() ).collect::< Vec< _ > >(); let exp : Vec< CellVal > = each_into([ 9, 0, 0, 0, 0, 1, 0, 0, 0 ]).collect(); a_id!( got, exp ); a_id!( board.blocks().count(), 9 ); } #[ test ] fn select() { let board = Board::default(); let indices = board.block_cells( ( 0, 0 ).into() ); let got : Vec< CellVal > = board.select( indices ).collect(); let exp : Vec< CellVal > = each_into([ 3, 1, 0, 0, 0, 6, 0, 0, 0 ]).collect(); a_id!( got, exp ); let indices = board.block_cells( ( 1, 0 ).into() ); let got : Vec< CellVal > = board.select( indices ).collect(); let exp : Vec< CellVal > = each_into([ 0, 0, 0, 1, 0, 9, 0, 8, 0 ]).collect(); a_id!( got, exp ); let indices = board.block_cells( ( 2, 2 ).into() ); let got : Vec< CellVal > = board.select( indices ).collect(); let exp : Vec< CellVal > = each_into([ 9, 0, 0, 0, 0, 1, 0, 0, 0 ]).collect(); a_id!( got, exp ); } #[ test ] fn select_mut() { let mut board = Board::default(); let indices = board.block_cells( ( 0, 0 ).into() ); board.select_mut( indices ).for_each( | e | *e = *e + 1.into() ); let indices = board.block_cells( ( 0, 0 ).into() ); let got : Vec< CellVal > = board.select( indices ).collect(); let exp : Vec< CellVal > = each_into([ 4, 2, 1, 1, 1, 7, 1, 1, 1 ]).collect(); a_id!( got, exp ); } #[ test ] fn cross_error() { let board = Board::default(); let exp = 14; let got = board.cross_error( ( 0, 0 ).into() ); a_id!( got, exp ); let exp = 12; let got = board.cross_error( ( 1, 0 ).into() ); a_id!( got, exp ); let exp = 14; let got = board.cross_error( ( 8, 8 ).into() ); a_id!( got, exp ); } #[ test ] fn total_error() { let board = Board::default(); let exp = 116; let got = board.total_error(); a_id!( got, exp ); } #[ test ] fn cells_swap() { let storage : Vec< CellVal > = each_into ([ 0,1,0, 0,0,0, 0,2,0, 0,0,6, 1,0,9, 0,0,5, 0,0,0, 0,8,0, 0,0,0, 0,2,0, 8,0,4, 0,5,0, 0,0,4, 0,7,0, 0,0,0, 0,0,0, 0,6,0, 0,0,8, 0,6,0, 0,0,0, 9,0,0, 0,0,9, 4,0,5, 0,0,1, 0,0,0, 0,0,7, 0,0,3, ]).collect(); let exp = Board::new( storage ); let mut got = Board::default(); got.cells_swap( ( 0, 0 ).into(), ( 8, 8 ).into() ); a_id!( got, exp ); let storage : Vec< CellVal > = each_into ([ 3,1,0, 0,0,0, 0,2,0, 0,0,6, 1,0,9, 0,0,2, 0,0,0, 0,8,0, 0,0,0, 0,5,0, 8,0,4, 0,5,0, 0,0,4, 0,7,0, 0,0,0, 0,0,0, 0,6,0, 0,0,8, 0,6,0, 0,0,0, 9,0,0, 0,0,9, 4,0,5, 0,0,1, 0,0,0, 0,0,7, 0,0,0, ]).collect(); let exp = Board::new( storage ); let mut got = Board::default(); got.cells_swap( ( 1, 3 ).into(), ( 8, 1 ).into() ); dbg!( &got ); dbg!( &exp ); a_id!( got, exp ); } #[ test ] fn block_missing_vals() { let board = Board::default(); let got = board.block_missing_vals( ( 0, 0 ).into() ); let exp = hset!( 2, 4, 5, 7, 8, 9 ); a_id!( got, exp ); } #[ test ] fn fill_missing_randomly() { let hrng = Hrng::master_with_seed( "seed1".into() ); let mut board = Board::default(); println!( "{board}" ); board.fill_missing_randomly( hrng ); for cell in board.cells() { // println!( "cell : {cell:?}" ); assert!( cell.1 != 0.into() ); } for block in board.blocks() { let missing = board.block_missing_vals( block ); assert!( missing.len() == 0 ); } println!( "{board} with hash {}", hash( &board ) ); println!( "total_error : {}", board.total_error() ); let hrng = Hrng::master_with_seed( "seed1".into() ); let mut board2 = Board::default(); println!( "{board2}" ); board2.fill_missing_randomly( hrng ); println!( "{board2} with hash {}", hash( &board2 ) ); assert_eq!( hash( &board ), hash( &board2 ) ); // assert!( false ); } fn hash< T : std::hash::Hash >( t : &T ) -> u64 { use std::hash::Hasher; use std::collections::hash_map::DefaultHasher; let mut hasher = DefaultHasher::new(); t.hash( &mut hasher ); hasher.finish() } // 310 000 020 // 006 109 005 // 000 080 000 // 020 804 050 // 004 070 000 // 000 060 008 // 060 000 900 // 009 405 001 // 000 007 000