pileOfShit.pop()

This commit is contained in:
Martin HART 2020-10-27 15:58:19 +01:00
parent c27c403827
commit ac6df77d8f
2 changed files with 0 additions and 290 deletions

View File

@ -8,4 +8,3 @@ edition = "2018"
[dependencies]
clap = "2.33.3"
queues = "1.1.0"

View File

@ -14,139 +14,9 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
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<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.
fn open_file(filename: &str) -> io::Result<String> {
let content = fs::read_to_string(filename)?;
@ -178,168 +48,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
#[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());
}
}