diff --git a/Cargo.toml b/Cargo.toml index 740a020..863e846 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,3 @@ edition = "2018" [dependencies] clap = "2.33.3" -queues = "1.1.0" diff --git a/src/main.rs b/src/main.rs index 89a53a0..b910ab1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,139 +14,9 @@ // along with this program. If not, see . use clap::{App, Arg}; -use queues::*; use std::fs; use std::io; -/// Struct to store the world. -struct World { - x: u32, - y: u32, - map: Vec, -} - -impl World { - /// Create a new map full of dots. - fn create(&mut self) { - self.map = vec!['.'; (self.x * self.y) as usize]; - } - /// Set robot on the map. - fn set_robot(&mut self, r: &Robot) { - self.map[(r.p.x + (r.p.y * self.x as i32)) as usize] = match r.o { - Orientation::N => '↑', - Orientation::S => '↓', - Orientation::E => '→', - Orientation::W => '←', - } - } - /// Check if a position is free. - fn empty_position(&mut self, p: &Position) -> bool { - self.map[(p.x + (p.y * self.x as i32)) as usize] == '.' - } - /// Place robot on the map after checking if the position is valid. - fn place_robot(&mut self, r: &Robot) -> Result<(), String> { - match r.p.is_valid(&self) { - Ok(_) => Ok(self.set_robot(r)), - Err(e) => Err(e), - } - } -} - -/// Struct to store robot position. -struct Position { - x: i32, - y: i32, -} - -impl Position { - /// Check if position is in the map. - fn is_valid(&self, w: &World) -> Result<(), String> { - if (self.x, self.y) > (0, 0) && (self.x, self.y) < (w.x as i32, w.y as i32) { - Ok(()) - } else { - Err(String::from("Invalid position.")) - } - } -} - -/// A Robot *aka droid* is represented here. -/// Each robot must have a unique id. -struct Robot { - id: u32, - o: Orientation, - p: Position, - q: Queue, -} - -impl Robot { - /// Create a empty Robot. - fn new() -> Robot { - Robot { - id: 0, - o: Orientation::N, - p: Position { x: 0, y: 0 }, - q: queue![], - } - } - /// Initialize a new Robot. - fn create(&mut self, id: u32, o: Orientation, p: Position, s: String) { - let mut q: Queue = queue![]; - for c in s.chars() { - q.add(c); - } - self.id = id; - self.o = o; - self.p = p; - self.q = q; - } - /// Apply forward instruction to the robot. - fn move_forward(&mut self, w: &mut World) { - w.map[(self.p.x + (self.p.y * w.x as i32)) as usize] = '.'; - match self.o { - Orientation::N => self.p.y -= 1, - Orientation::S => self.p.y += 1, - Orientation::E => self.p.x += 1, - Orientation::W => self.p.x -= 1, - } - } - /// Apply North orientation to the robot. - fn set_north(&mut self) { - self.o = Orientation::N - } - /// Apply South orientation to the robot. - fn set_south(&mut self) { - self.o = Orientation::S - } - /// Apply East orientation to the robot. - fn set_east(&mut self) { - self.o = Orientation::E - } - /// Apply West orientation to the robot. - fn set_west(&mut self) { - self.o = Orientation::W - } -} - -/// Enum to store all possible orientations. -enum Orientation { - N, - E, - S, - W, -} - -/// Parse char and return corresponding orientation. -fn parse_orientation(c: char) -> Result { - match c { - 'N' => Ok(Orientation::N), - 'E' => Ok(Orientation::E), - 'S' => Ok(Orientation::S), - 'W' => Ok(Orientation::W), - _ => Err("Invalid character, does not match any orientations"), - } -} - - /// Retrieve the content of a file and return it as a string. fn open_file(filename: &str) -> io::Result { let content = fs::read_to_string(filename)?; @@ -178,168 +48,9 @@ fn main() -> Result<(), Box> { #[cfg(test)] mod tests { use super::*; - - #[test] - fn test_parse_orientation() { - assert!(parse_orientation('N').is_ok()); - assert!(parse_orientation('E').is_ok()); - assert!(parse_orientation('S').is_ok()); - assert!(parse_orientation('W').is_ok()); - assert!(parse_orientation('Z').is_err()); - } - #[test] fn test_open_file() { assert!(open_file("two_robots.txt").is_ok()); assert!(open_file("test_unexisting_file.extension").is_err()); } - - #[test] - fn test_create() { - let mut w: World = World { - x: 5, - y: 5, - map: Vec::new(), - }; - w.create(); - assert_eq!(w.map, vec!['.'; 25]); - } - - #[test] - fn test_new_robot() { - let mut r: Robot = Robot::new(); - assert_eq!(r.id, 0); - assert!(matches!(r.o, Orientation::N)); - - assert_eq!(r.p.x, 0); - assert_eq!(r.p.y, 0); - - assert_eq!(r.q.size(), 0); - } - - #[test] - fn test_create_robot() { - let mut r: Robot = Robot::new(); - r.create(1, Orientation::N, Position { x: 1, y: 1 }, "FF".to_string()); - assert_eq!(r.id, 1); - assert!(matches!(r.o, Orientation::N)); - - assert_eq!(r.p.x, 1); - assert_eq!(r.p.y, 1); - - assert_eq!(r.q.peek(), Ok('F')); - assert_eq!(r.q.peek(), Ok('F')); - } - - #[test] - fn test_set_robot() { - let r = Robot { - id: 0, - o: Orientation::N, - p: Position { x: 0, y: 0 }, - q: Queue::new(), - }; - let mut w: World = World { - x: 2, - y: 2, - map: Vec::new(), - }; - w.create(); - w.set_robot(&r); - assert_eq!(w.map, vec!['↑', '.', '.', '.']); - } - - #[test] - fn test_move_robot() { - let mut r: Robot = Robot { - id: 0, - o: Orientation::N, - p: Position { x: 1, y: 1 }, - q: Queue::new(), - }; - let mut w: World = World { - x: 2, - y: 2, - map: Vec::new(), - }; - w.create(); - r.move_forward(&mut w); - assert_eq!(0, r.p.y); - } - - #[test] - fn test_place_robot() { - let mut r: Robot = Robot { - id: 0, - o: Orientation::N, - p: Position { x: 1, y: 1 }, - q: Queue::new(), - }; - let mut w: World = World { - x: 2, - y: 2, - map: Vec::new(), - }; - w.create(); - w.set_robot(&r); - assert_eq!(w.map, vec!['.', '.', '.', '↑']); - r.move_forward(&mut w); - assert!(w.place_robot(&r).is_ok()); - assert_eq!(w.map, vec!['.', '↑', '.', '.']); - } - - #[test] - #[should_panic] - fn test_place_robot_fail() { - let mut r: Robot = Robot { - id: 0, - o: Orientation::N, - p: Position { x: 1, y: 1 }, - q: Queue::new(), - }; - let mut w: World = World { - x: 2, - y: 2, - map: Vec::new(), - }; - w.create(); - w.set_robot(&r); - r.move_forward(&mut w); - r.move_forward(&mut w); - assert!(w.place_robot(&r).is_ok()); - } - - #[test] - fn test_empty_position() { - let mut w: World = World { - x: 2, - y: 2, - map: Vec::new(), - }; - w.create(); - assert!(w.empty_position(&Position { x: 0, y: 0 })); - } - - #[test] - fn test_valid_position() { - let p: Position = Position { x: 1, y: 1 }; - let w: World = World { - x: 5, - y: 5, - map: Vec::new(), - }; - assert!(p.is_valid(&w).is_ok()); - } - - #[test] - #[should_panic] - fn test_invalid_position() { - let p: Position = Position { x: -1, y: 1 }; - let w: World = World { - x: 5, - y: 5, - map: Vec::new(), - }; - assert!(p.is_valid(&w).is_ok()); - } }