pileOfShit.pop()
This commit is contained in:
parent
c27c403827
commit
ac6df77d8f
@ -8,4 +8,3 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = "2.33.3"
|
clap = "2.33.3"
|
||||||
queues = "1.1.0"
|
|
||||||
|
289
src/main.rs
289
src/main.rs
@ -14,139 +14,9 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use queues::*;
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
/// Struct to store the world.
|
|
||||||
struct World {
|
|
||||||
x: u32,
|
|
||||||
y: u32,
|
|
||||||
map: Vec<char>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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<char>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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<char> = 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<Orientation, &'static str> {
|
|
||||||
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.
|
/// Retrieve the content of a file and return it as a string.
|
||||||
fn open_file(filename: &str) -> io::Result<String> {
|
fn open_file(filename: &str) -> io::Result<String> {
|
||||||
let content = fs::read_to_string(filename)?;
|
let content = fs::read_to_string(filename)?;
|
||||||
@ -178,168 +48,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
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]
|
#[test]
|
||||||
fn test_open_file() {
|
fn test_open_file() {
|
||||||
assert!(open_file("two_robots.txt").is_ok());
|
assert!(open_file("two_robots.txt").is_ok());
|
||||||
assert!(open_file("test_unexisting_file.extension").is_err());
|
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user