1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
#[derive(Debug,PartialEq,PartialOrd)] pub struct Coordinate { x: i64, y: i64, z: i64, } impl Coordinate { pub fn new() -> Result<Self, &'static str> { Ok(Coordinate { x: 0, y: 0, z: 0 }) } pub fn at(x: i64, y: i64, z: i64) -> Result<Self, &'static str> { if x + y + z == 0 { Ok(Coordinate { x: x, y: y, z: z }) } else { Err("Invalid cubic coordinates") } } pub fn neighbors(&self) -> Vec<Coordinate> { vec![ Coordinate::at(self.x + 1, self.y, self.z - 1).unwrap(), Coordinate::at(self.x + 1, self.y - 1, self.z).unwrap(), Coordinate::at(self.x - 1, self.y + 1, self.z).unwrap(), Coordinate::at(self.x - 1, self.y, self.z + 1).unwrap(), Coordinate::at(self.x, self.y + 1, self.z - 1).unwrap(), Coordinate::at(self.x, self.y - 1, self.z + 1).unwrap(), ] } pub fn distance_to(&self, other: Coordinate) -> i64 { ( (self.x - other.x).abs() + (self.y - other.y).abs() + (self.z - other.z).abs() ) / 2 } } #[cfg(test)] mod tests { use super::*; #[test] fn it_makes_a_new_one() { let coord = Coordinate::new().unwrap(); assert_eq!(coord.x, 0); assert_eq!(coord.y, 0); assert_eq!(coord.z, 0); } #[test] fn it_accepts_args_in_constructor() { let coord = Coordinate::at(-3, -1, 4).unwrap(); assert_eq!(coord.x, -3); assert_eq!(coord.y, -1); assert_eq!(coord.z, 4); } #[test] fn it_rejects_invalid_cube_coordinates() { let coord = Coordinate::at(3, 1, 4); assert!(coord.is_err()); } #[test] fn it_generates_a_list_of_neighbors() { let coord = Coordinate::new().unwrap(); let expected = vec![ Coordinate::at(1, 0, -1).unwrap(), Coordinate::at(1, -1, 0).unwrap(), Coordinate::at(-1, 1, 0).unwrap(), Coordinate::at(-1, 0, 1).unwrap(), Coordinate::at(0, 1, -1).unwrap(), Coordinate::at(0, -1, 1).unwrap(), ]; assert_eq!(coord.neighbors(), expected); } #[test] fn it_calcuates_distances() { let coord_a = Coordinate::at(-3, -1, 4).unwrap(); let coord_b = Coordinate::at(2, 7, -9).unwrap(); assert_eq!(coord_a.distance_to(coord_b), 13); } }