use optimization_tools::*;
use sudoku::*;
use test_tools::prelude::*;
use deterministic_rand::Hrng;
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()
{
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 ) );
}
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()
}