2019-12-13 13:40:32 +01:00
use itertools ::join ;
use std ::collections ::HashMap ;
2019-12-13 19:36:47 +01:00
use std ::fmt ::Display ;
use std ::hash ::BuildHasher ;
2019-12-15 11:49:30 +01:00
use std ::ops ::{ Add , AddAssign } ;
2019-12-13 13:40:32 +01:00
#[ derive(Hash, PartialEq, Eq, Debug, Clone, Copy) ]
pub struct Position2D {
2019-12-13 19:29:22 +01:00
pub x : i64 ,
pub y : i64 ,
2019-12-13 13:40:32 +01:00
}
2019-12-15 11:49:30 +01:00
pub enum Direction {
Up ,
Down ,
Left ,
Right ,
}
2019-12-13 13:40:32 +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 }
}
2019-12-15 11:49:30 +01:00
pub fn draw_ascii < T : Display , S : BuildHasher > (
coordinates : & HashMap < Position2D , T , S > ,
default : T ,
) -> String {
2019-12-13 13:40:32 +01:00
let b = get_boundaries ( & coordinates . keys ( ) . collect ::< Vec < _ > > ( ) ) ;
join (
( b . y_min ..= b . y_max ) . rev ( ) . map ( | y | {
2019-12-13 19:29:22 +01:00
( b . x_min ..= b . x_max )
2019-12-13 13:40:32 +01:00
. map ( | x | {
coordinates
. get ( & ( x , y ) . into ( ) )
. unwrap_or ( & default )
. to_string ( )
} )
. collect ::< String > ( )
} ) ,
" \n " ,
)
}
2019-12-15 11:49:30 +01:00
impl Position2D {
pub fn mov ( & mut self , dir : & Direction ) {
* self = * self
+ match dir {
Direction ::Up = > ( 0 , 1 ) . into ( ) ,
Direction ::Right = > ( 1 , 0 ) . into ( ) ,
Direction ::Left = > ( - 1 , 0 ) . into ( ) ,
Direction ::Down = > ( 0 , - 1 ) . into ( ) ,
}
}
}
impl AddAssign for Position2D {
fn add_assign ( & mut self , rhs : Position2D ) {
* self = * self + rhs ;
}
}
impl Add for Position2D {
2019-12-13 13:40:32 +01:00
type Output = Position2D ;
fn add ( self , rhs : Position2D ) -> Position2D {
Position2D {
x : self . x + rhs . x ,
y : self . y + rhs . y ,
}
}
}
impl From < ( i64 , i64 ) > for Position2D {
fn from ( tuple : ( i64 , i64 ) ) -> Position2D {
Position2D {
x : tuple . 0 ,
y : tuple . 1 ,
}
}
}
#[ cfg(test) ]
mod tests { }