2020-12-17 14:51:05 +01:00
pub mod cell ;
pub mod direction ;
pub mod position ;
pub use direction ::* ;
pub use position ::* ;
2020-12-11 10:18:58 +01:00
2020-12-17 14:51:05 +01:00
use itertools ::join ;
use std ::{ collections ::HashMap , fmt ::Display , hash ::BuildHasher } ;
2020-12-17 14:04:05 +01:00
#[ derive(Debug, Clone) ]
2020-12-17 21:30:30 +01:00
pub struct Grid < const D : usize , T : Display + Default > {
pub fields : HashMap < PositionND < D > , T > ,
2020-12-17 14:04:05 +01:00
}
2020-12-17 21:30:30 +01:00
impl < const D : usize , T : Display + Default + Copy > Grid < D , T > {
//pub fn get_convert<Pos: Into<P>>(&self, pos: Pos) -> T {
//self.fields.get(&pos.into()).copied().unwrap_or_else(|| T::default())
//}
2020-12-17 14:04:05 +01:00
2020-12-17 21:30:30 +01:00
pub fn get ( & self , pos : & PositionND < D > ) -> T {
2020-12-17 16:22:26 +01:00
self . fields . get ( pos ) . copied ( ) . unwrap_or_else ( | | T ::default ( ) )
}
2020-12-17 21:30:30 +01:00
pub fn insert < Pos : Into < PositionND < D > > > ( & mut self , pos : Pos , t : T ) {
2020-12-17 14:04:05 +01:00
self . fields . insert ( pos . into ( ) , t ) ;
}
}
2020-12-17 21:30:30 +01:00
impl < const D : usize , T : Display + Default > std ::iter ::FromIterator < ( PositionND < D > , T ) > for Grid < D , T > {
fn from_iter < I : IntoIterator < Item = ( PositionND < D > , T ) > > ( iter : I ) -> Self {
2020-12-17 14:13:02 +01:00
Grid {
fields : iter . into_iter ( ) . collect ( ) ,
}
}
}
2020-12-17 21:30:30 +01:00
// impl<T: Display + Default + Copy> Grid<Position2D, T> {
// fn draw_ascii(&self) -> String {
// draw_ascii(&self.fields)
// }
// }
2020-12-17 14:04:05 +01:00
2020-12-11 10:18:58 +01:00
struct Boundaries {
x_min : i64 ,
x_max : i64 ,
y_min : i64 ,
y_max : i64 ,
}
#[ rustfmt::skip ]
fn get_boundaries ( input : & [ & Position2D ] ) -> Boundaries {
let x_min = input . iter ( ) . min_by_key ( | k | k . x ) . map ( | p | p . x ) . unwrap_or ( 0 ) ;
let x_max = input . iter ( ) . max_by_key ( | k | k . x ) . map ( | p | p . x ) . unwrap_or ( 0 ) ;
let y_min = input . iter ( ) . min_by_key ( | k | k . y ) . map ( | p | p . y ) . unwrap_or ( 0 ) ;
let y_max = input . iter ( ) . max_by_key ( | k | k . y ) . map ( | p | p . y ) . unwrap_or ( 0 ) ;
Boundaries { x_min , x_max , y_min , y_max }
}
2020-12-11 12:04:38 +01:00
pub fn draw_ascii < T : Display + Default , S : BuildHasher > ( coordinates : & HashMap < Position2D , T , S > ) -> String {
2020-12-11 10:18:58 +01:00
let b = get_boundaries ( & coordinates . keys ( ) . collect ::< Vec < _ > > ( ) ) ;
join (
( b . y_min ..= b . y_max ) . rev ( ) . map ( | y | {
( b . x_min ..= b . x_max )
2020-12-11 12:04:38 +01:00
. map ( | x | coordinates . get ( & ( x , y ) . into ( ) ) . unwrap_or ( & T ::default ( ) ) . to_string ( ) )
2020-12-11 10:18:58 +01:00
. collect ::< String > ( )
} ) ,
" \n " ,
)
}
#[ cfg(test) ]
mod tests {
use super ::* ;
#[ test ]
fn test_add ( ) {
assert_eq! ( Position2D { x : 0 , y : 2 } + Position2D { x : - 1 , y : 0 } , ( - 1 , 2 ) . into ( ) ) ;
assert_eq! ( Position2D { x : 0 , y : - 1 } + Direction ::Up , ( 0 , 0 ) . into ( ) ) ;
}
}