Решение на Dungeons and Compilers от Александър Стоилов
Към профила на Александър Стоилов
Резултати
- 15 точки от тестове
- 0 бонус точки
- 15 точки общо
- 11 успешни тест(а)
- 4 неуспешни тест(а)
Код
use std::collections::VecDeque;
use std::collections::HashMap;
use std::io::BufRead;
#[derive(Debug)]
pub enum Errors {
DuplicateRoom(String),
UnknownRoom(String),
IoError(std::io::Error),
LineParseError { line_number: usize },
DirectionParseError(String),
}
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
pub enum Direction {
North,
South,
East,
West,
}
pub struct Room {
pub name: String,
// може би по-добра идея е
// neigh_E: String,
// neigh_W: String, ... (или масив от 4 стринга с конвенция [0] <=> E, [1] <=> W, ...)
pub neighs: HashMap<Direction, String>,
}
pub struct Dungeon {
pub rooms: HashMap<String, Room>,
}
impl Dungeon {
pub fn new() -> Self {
Self {
rooms: HashMap::new(),
}
}
pub fn add_room(&mut self, name: &str) -> Result<(), Errors> {
if self.rooms.contains_key(name) {
Err(Errors::DuplicateRoom(name.to_string()))
} else {
self.rooms.insert(
name.to_string(),
Room {
name: name.to_string(),
neighs: HashMap::new(),
},
);
Ok(())
}
}
pub fn get_room(&self, room_name: &str) -> Result<&Room, Errors> {
if self.rooms.contains_key(room_name) {
Ok(self.rooms.get(room_name).unwrap())
} else {
Err(Errors::UnknownRoom(room_name.to_string()))
}
}
pub fn set_link(&mut self, room_name: &str, direction: Direction, other_room_name: &str) -> Result<(), Errors> {
if self.rooms.contains_key(room_name) {
if self.rooms.contains_key(other_room_name) {
// добавяме 'room -> dir -> other'
self.rooms.get_mut(room_name).unwrap().neighs.insert(direction, other_room_name.to_string());
let reverse: Direction = match direction {
Direction::North => Direction::South,
Direction::South => Direction::North,
Direction::East => Direction::West,
Direction::West => Direction::East,
};
// добавяме 'other -> reverse_dir -> room'
self.rooms.get_mut(other_room_name).unwrap().neighs.insert(reverse, room_name.to_string());
Ok(())
} else {
Err(Errors::UnknownRoom(other_room_name.to_string()))
}
} else {
Err(Errors::UnknownRoom(room_name.to_string()))
}
}
pub fn get_next_room(&self, room_name: &str, direction: Direction) -> Result<Option<&Room>, Errors> {
if self.rooms.contains_key(room_name) {
if self.rooms.get(room_name).unwrap().neighs.contains_key(&direction) {
let neigh_as_str: &String = self.rooms.get(room_name).unwrap().neighs.get(&direction).unwrap();
let neigh_as_room: &Room = self.rooms.get(neigh_as_str).unwrap();
Ok(Some(neigh_as_room))
} else {
Ok(None)
}
} else {
Err(Errors::UnknownRoom(room_name.to_string()))
}
}
pub fn from_reader<B: BufRead>(reader: B) -> Result<Self, Errors> {
let mut line: String = String::new();
let mut reader: B = reader;
let mut line_number: usize = 0;
let mut dungeon: Dungeon = Dungeon::new();
let mut order: [bool; 3] = [false, false, false]; // [0] <=> "## Rooms", [1] <=> "\n", [2] <=> "## Links"
while reader.read_line(&mut line).unwrap() > 0 {
// Rooms header
if line_number == 0 {
if line == "## Rooms\n" {
order[0] = true;
} else {
return Err(Errors::IoError(Ok(line).err().unwrap()));
}
}
// New line b/w rooms and links
else if line == "\n" && order[0] && !order[1] && !order[2] {
order[1] = true;
}
// Links header
else if line == "## Links\n" && order[0] && order[1] && !order[2] {
order[2] = true;
}
// data row
else if line.starts_with("- ") {
// format <=> "- <room>"
if order[0] && !order[1] && !order[2] {
line.replace_range(0..2, "");
let mut room: String = line.clone();
room.pop().unwrap();
dungeon.add_room(room.as_str())?;
}
// format <=> "- <room> -> <dir> -> <other_room>"
else if line.matches(" -> ").count() == 2 && order[0] && order[1] && order[2] {
line.replace_range(0..2, "");
let last_char: char = line.pop().unwrap();
// eventually ще стигнем до последния link ред, който не завършва на \n
if last_char != '\n' { line.push(last_char); }
let words: Vec<&str> = line.split_terminator(" -> ").collect();
let room: &str = words.get(0).unwrap();
let dir: &str = words.get(1).unwrap();
let other_room: &str = words.get(2).unwrap();
let dir: Direction = match dir {
"North" => Direction::North,
"South" => Direction::South,
"East" => Direction::East,
"West" => Direction::West,
_ => return Err(Errors::DirectionParseError(dir.to_string()))
};
dungeon.set_link(room, dir, other_room)?;
} else {
return Err(Errors::LineParseError { line_number });
}
} else {
return Err(Errors::LineParseError { line_number });
}
line_number += 1;
line.clear();
}
Ok(dungeon)
}
pub fn find_path(&self, start_room_name: &str, end_room_name: &str) -> Result<Option<Vec<&Room>>, Errors> {
if self.get_room(start_room_name).is_err() {
return Err(Errors::UnknownRoom(start_room_name.to_string()));
} else if self.get_room(end_room_name).is_err() {
return Err(Errors::UnknownRoom(end_room_name.to_string()));
};
let mut rooms: VecDeque<String> = VecDeque::new();
let mut visited: HashMap<String, bool> = HashMap::new(); // visited[room_str] = true/false
let mut parents: HashMap<String, String> = HashMap::new(); // parents[room_str] = parent_str
rooms.push_front(start_room_name.to_string());
visited.insert(start_room_name.to_string(), true);
while !rooms.is_empty() {
let curr: String = rooms.pop_back().unwrap().clone();
if curr == end_room_name { break; }
for (_direction, neigh) in self.rooms.get(&curr).unwrap().neighs.iter() {
if !visited.contains_key(&neigh.clone()) {
parents.insert(neigh.clone(), curr.clone());
visited.insert(neigh.clone(), true);
rooms.push_front(neigh.to_string());
}
}
}
let mut result_path: Vec<&Room> = Vec::new();
if !parents.contains_key(end_room_name) { return Ok(None); }
let mut curr: &str = end_room_name;
let curr_as_room: &Room = self.get_room(curr).unwrap();
result_path.push(curr_as_room);
while parents.contains_key(curr) {
let parent: &String = parents.get(curr).unwrap();
let parent_as_room: &Room = self.get_room(parent).unwrap();
curr = parents.get(curr).unwrap().as_str();
result_path.push(parent_as_room);
}
result_path.reverse();
Ok(Some(result_path))
}
}
// TESTS DESCRIPTION
// test_basic[1..3] -> given;
// own_tests_test[1..10] -> invalid reader object passed, all should panic
// own_tests_test[11..] -> functionalities & несполучлив опит за error type check
#[test]
fn test_basic_1() {
let mut dungeon = Dungeon::new();
dungeon.add_room("Entrance").unwrap();
dungeon.add_room("Hallway").unwrap();
dungeon.set_link("Entrance", Direction::East, "Hallway").unwrap();
assert_eq!(dungeon.get_room("Entrance").unwrap().name, "Entrance");
assert_eq!(dungeon.get_next_room("Entrance", Direction::East).unwrap().unwrap().name, "Hallway");
}
#[allow(unused)]
const TEST_INPUT_1: &str = "
## Rooms
- Entrance
- Hallway
## Links
- Entrance -> East -> Hallway
";
#[test]
fn test_basic_2() {
// .trim() за да премахнем първия и последния ред:
let dungeon = Dungeon::from_reader(TEST_INPUT_1.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("Entrance").unwrap().name, "Entrance");
assert_eq!(dungeon.get_room("Hallway").unwrap().name, "Hallway");
assert_eq!(dungeon.get_next_room("Entrance", Direction::East).unwrap().unwrap().name, "Hallway");
}
#[test]
fn test_basic_3() {
let mut dungeon = Dungeon::new();
dungeon.add_room("Entrance").unwrap();
dungeon.add_room("Treasure Room").unwrap();
dungeon.set_link("Entrance", Direction::West, "Treasure Room").unwrap();
let path = dungeon.find_path("Entrance", "Treasure Room").unwrap().unwrap();
assert!(path.len() > 0);
}
#[allow(unused)]
const OWN_TESTS_INPUT_1: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
fn own_tests_test_1() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_1.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_2: &str = "
##Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_2() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_2.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_3: &str = "
## Rooms
- 1
- 2
##Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_3() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_3.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_4: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West-> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_4() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_4.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_5: &str = "
## Links
- 1 -> West -> 2
- 2 -> South -> 1
## Rooms
- 1
- 2
";
#[test]
#[should_panic]
fn own_tests_test_5() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_5.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_6: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South:) -> 1
";
#[test]
#[should_panic]
fn own_tests_test_6() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_6.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_7: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_7() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_7.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_8: &str = "
## Rooms
- 1
- 2
## Rooms
- 3
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_8() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_8.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_9: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> East -> 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_9() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_9.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_10: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_10() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_10.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_11: &str = "
## Rooms
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
## Links
- 1 -> East -> 2
- 10 -> West -> 6
- 9 -> North -> 6
- 3 -> North -> 8
- 4 -> South -> 8
- 4 -> East -> 7
- 7 -> South -> 2
- 5 -> East -> 9
- 5 -> North -> 3
";
#[test]
fn own_tests_test_11() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_11.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
assert_eq!(dungeon.get_room("2").unwrap().name, "2");
assert_eq!(dungeon.get_room("10").unwrap().name, "10");
let result_path = dungeon.find_path("1", "10").unwrap().unwrap();
let mut rooms: Vec<String> = Vec::new();
for room in result_path {
rooms.push(room.name.to_string());
}
assert_eq!(rooms, vec!["1", "2", "7", "4", "8", "3", "5", "9", "6", "10"]);
/*
4------7
| |
8\1#---2/10#
| |
3 6
| |
5---------9
*/
}
#[allow(unused)]
const OWN_TESTS_INPUT_12: &str = "
## Rooms
- 1
- 2
- 3
## Links
- 1 -> West -> 2
- 2 -> East -> 3
";
#[test]
fn own_tests_test_12() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_12.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
assert_eq!(dungeon.get_room("2").unwrap().name, "2");
assert_eq!(dungeon.get_room("3").unwrap().name, "3");
assert_eq!(dungeon.get_next_room("1", Direction::West).unwrap().unwrap().name, "2");
assert_eq!(dungeon.get_next_room("2", Direction::East).unwrap().unwrap().name, "3");
let result_path = dungeon.find_path("1", "3").unwrap().unwrap();
let mut rooms: Vec<String> = Vec::new();
for room in result_path {
rooms.push(room.name.to_string());
}
assert_eq!(rooms, vec!["1", "2", "3"]);
}
#[test]
fn own_tests_test_13() {
let mut dungeon = Dungeon::new();
dungeon.add_room("1").unwrap();
dungeon.add_room("2").unwrap();
dungeon.add_room("3").unwrap();
dungeon.add_room("4").unwrap();
dungeon.add_room("5").unwrap();
dungeon.add_room("6").unwrap();
dungeon.add_room("A").unwrap();
dungeon.add_room("B").unwrap();
dungeon.add_room("C").unwrap();
dungeon.add_room("D").unwrap();
dungeon.add_room("кирилица").unwrap();
dungeon.add_room("¥«¾ÈÚñüÿ").unwrap();
assert_eq!(dungeon.get_room("2").unwrap().name, "2");
assert_eq!(dungeon.get_room("A").unwrap().name, "A");
assert_eq!(dungeon.get_room("кирилица").unwrap().name, "кирилица");
assert_eq!(dungeon.get_room("¥«¾ÈÚñüÿ").unwrap().name, "¥«¾ÈÚñüÿ");
dungeon.set_link("1", Direction::West, "2").unwrap();
dungeon.set_link("2", Direction::North, "3").unwrap();
dungeon.set_link("3", Direction::East, "4").unwrap();
dungeon.set_link("4", Direction::South, "5").unwrap();
dungeon.set_link("6", Direction::East, "5").unwrap();
assert_eq!(dungeon.get_next_room("A", Direction::North).unwrap().is_none(), true);
assert_eq!(dungeon.get_next_room("3", Direction::North).unwrap().is_none(), true);
assert_eq!(dungeon.get_next_room("1", Direction::West).unwrap().unwrap().name, "2");
assert_eq!(dungeon.get_next_room("4", Direction::West).unwrap().unwrap().name, "3");
assert_eq!(dungeon.get_next_room("4", Direction::South).unwrap().unwrap().name, "5");
let result_path = dungeon.find_path("1", "6").unwrap().unwrap();
let mut names: Vec<String> = Vec::new();
for room in result_path {
names.push(room.name.to_string());
}
assert_eq!(names, vec!["1", "2", "3", "4", "5", "6"]);
}
#[test]
fn own_tests_test_14() {
let mut dungeon = Dungeon::new();
dungeon.add_room("1").unwrap();
dungeon.add_room("2").unwrap();
dungeon.add_room("3").unwrap();
// иска PartialEq на Errors, а не може, понеже имаме std::io::Error ?
// let should_err = dungeon.add_room("1").unwrap_err();
// assert_eq!(should_err, Err(Errors::DuplicateRoom("1".to_string())).unwrap_err());
// ||
// if let Err(e) = dungeon.add_room("1") {
// assert_eq!(e, Errors::DuplicateRoom("1".to_string()));
// }
dungeon.set_link("1", Direction::West, "2").unwrap();
dungeon.set_link("2", Direction::North, "3").unwrap();
}
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20220116-3533338-1v2payn/solution) Finished test [unoptimized + debuginfo] target(s) in 4.06s Running tests/solution_test.rs (target/debug/deps/solution_test-2e292b23ac75572c) running 15 tests test solution_test::test_adding_rooms_1 ... ok test solution_test::test_adding_rooms_2 ... ok test solution_test::test_cyrillic_room_names ... ok test solution_test::test_finding_a_direct_path ... ok test solution_test::test_finding_a_reflexive_path ... FAILED test solution_test::test_finding_an_indirect_path ... ok test solution_test::test_finding_no_path ... ok test solution_test::test_invalid_parsing ... FAILED test solution_test::test_io_error ... FAILED test solution_test::test_overwriting_a_room_link ... ok test solution_test::test_parsing_cyrillic_rooms ... ok test solution_test::test_parsing_no_rooms_or_links ... FAILED test solution_test::test_parsing_rooms ... ok test solution_test::test_room_errors ... ok test solution_test::test_room_links ... ok failures: ---- solution_test::test_finding_a_reflexive_path stdout ---- thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:360:71 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:354:5 ---- solution_test::test_invalid_parsing stdout ---- thread 'main' panicked at 'assertion failed: matches!(Dungeon :: from_reader(\"\".as_bytes()),\n Err(Errors :: LineParseError { line_number : 0 }))', tests/solution_test.rs:276:5 ---- solution_test::test_io_error stdout ---- thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: Other, error: "fill_buf error!" }', /tmp/d20220116-3533338-1v2payn/solution/src/lib.rs:107:43 thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: Other, error: "fill_buf error!" }', tests/solution_test.rs:194:5 ---- solution_test::test_parsing_no_rooms_or_links stdout ---- thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: LineParseError { line_number: 2 }', tests/solution_test.rs:237:72 failures: solution_test::test_finding_a_reflexive_path solution_test::test_invalid_parsing solution_test::test_io_error solution_test::test_parsing_no_rooms_or_links test result: FAILED. 11 passed; 4 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass '--test solution_test'
История (3 версии и 0 коментара)
Александър качи решение на 10.01.2022 18:30 (преди над 3 години)
use std::collections::VecDeque;
use std::collections::HashMap;
-use std::io::{BufRead};
+use std::io::BufRead;
#[derive(Debug)]
pub enum Errors {
DuplicateRoom(String),
UnknownRoom(String),
IoError(std::io::Error),
LineParseError { line_number: usize },
DirectionParseError(String),
}
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
pub enum Direction {
North,
South,
East,
West,
}
pub struct Room {
pub name: String,
// може би по-добра идея е
// neigh_E: String,
// neigh_W: String, ... (или масив от 4 стринга с конвенция [0] <=> E, [1] <=> W, ...)
pub neighs: HashMap<Direction, String>,
}
pub struct Dungeon {
pub rooms: HashMap<String, Room>,
}
impl Dungeon {
pub fn new() -> Self {
Self {
rooms: HashMap::new(),
}
}
pub fn add_room(&mut self, name: &str) -> Result<(), Errors> {
if self.rooms.contains_key(name) {
Err(Errors::DuplicateRoom(name.to_string()))
} else {
self.rooms.insert(
name.to_string(),
Room {
name: name.to_string(),
neighs: HashMap::new(),
},
);
Ok(())
}
}
pub fn get_room(&self, room_name: &str) -> Result<&Room, Errors> {
if self.rooms.contains_key(room_name) {
Ok(self.rooms.get(room_name).unwrap())
} else {
Err(Errors::UnknownRoom(room_name.to_string()))
}
}
pub fn set_link(&mut self, room_name: &str, direction: Direction, other_room_name: &str) -> Result<(), Errors> {
if self.rooms.contains_key(room_name) {
if self.rooms.contains_key(other_room_name) {
// добавяме 'room -> dir -> other'
self.rooms.get_mut(room_name).unwrap().neighs.insert(direction, other_room_name.to_string());
let reverse: Direction = match direction {
Direction::North => Direction::South,
Direction::South => Direction::North,
Direction::East => Direction::West,
Direction::West => Direction::East,
};
// добавяме 'other -> reverse_dir -> room'
self.rooms.get_mut(other_room_name).unwrap().neighs.insert(reverse, room_name.to_string());
Ok(())
} else {
Err(Errors::UnknownRoom(other_room_name.to_string()))
}
} else {
Err(Errors::UnknownRoom(room_name.to_string()))
}
}
pub fn get_next_room(&self, room_name: &str, direction: Direction) -> Result<Option<&Room>, Errors> {
if self.rooms.contains_key(room_name) {
if self.rooms.get(room_name).unwrap().neighs.contains_key(&direction) {
let neigh_as_str: &String = self.rooms.get(room_name).unwrap().neighs.get(&direction).unwrap();
let neigh_as_room: &Room = self.rooms.get(neigh_as_str).unwrap();
Ok(Some(neigh_as_room))
} else {
Ok(None)
}
} else {
Err(Errors::UnknownRoom(room_name.to_string()))
}
}
pub fn from_reader<B: BufRead>(reader: B) -> Result<Self, Errors> {
let mut line: String = String::new();
let mut reader: B = reader;
let mut line_number: usize = 0;
let mut dungeon: Dungeon = Dungeon::new();
let mut order: [bool; 3] = [false, false, false]; // [0] <=> "## Rooms", [1] <=> "\n", [2] <=> "## Links"
while reader.read_line(&mut line).unwrap() > 0 {
// Rooms header
if line_number == 0 {
if line == "## Rooms\n" {
order[0] = true;
} else {
return Err(Errors::IoError(Ok(line).err().unwrap()));
}
}
// New line b/w rooms and links
else if line == "\n" && order[0] && !order[1] && !order[2] {
order[1] = true;
}
// Links header
else if line == "## Links\n" && order[0] && order[1] && !order[2] {
order[2] = true;
}
// data row
else if line.starts_with("- ") {
// format <=> "- <room>"
if order[0] && !order[1] && !order[2] {
line.replace_range(0..2, "");
let mut room: String = line.clone();
room.pop().unwrap();
dungeon.add_room(room.as_str())?;
}
// format <=> "- <room> -> <dir> -> <other_room>"
else if line.matches(" -> ").count() == 2 && order[0] && order[1] && order[2] {
line.replace_range(0..2, "");
let last_char: char = line.pop().unwrap();
// eventually ще стигнем до последния link ред, който не завършва на \n
if last_char != '\n' { line.push(last_char); }
let words: Vec<&str> = line.split_terminator(" -> ").collect();
let room: &str = words.get(0).unwrap();
let dir: &str = words.get(1).unwrap();
let other_room: &str = words.get(2).unwrap();
let dir: Direction = match dir {
"North" => Direction::North,
"South" => Direction::South,
"East" => Direction::East,
"West" => Direction::West,
_ => return Err(Errors::DirectionParseError(dir.to_string()))
};
dungeon.set_link(room, dir, other_room)?;
}
else {
- return Err(Errors::IoError(Ok(line).err().unwrap()));
+ return Err(Errors::LineParseError {line_number});
}
}
else {
- return Err(Errors::IoError(Ok(line).err().unwrap()));
+ return Err(Errors::LineParseError {line_number});
}
line_number += 1;
line.clear();
}
Ok(dungeon)
}
pub fn find_path(&self, start_room_name: &str, end_room_name: &str) -> Result<Option<Vec<&Room>>, Errors> {
let mut rooms: VecDeque<String> = VecDeque::new();
let mut visited: HashMap<String, bool> = HashMap::new(); // visited[room_str] = true/false
let mut parents: HashMap<String, String> = HashMap::new(); // parents[room_str] = parent_str
rooms.push_front(start_room_name.to_string());
visited.insert(start_room_name.to_string(), true);
while !rooms.is_empty() {
let curr: String = rooms.pop_back().unwrap().clone();
if curr == end_room_name { break; }
for (_direction, neigh) in self.rooms.get(&curr).unwrap().neighs.iter() {
if !visited.contains_key(&neigh.clone()) {
parents.insert(neigh.clone(), curr.clone());
visited.insert(neigh.clone(), true);
rooms.push_front(neigh.to_string());
}
}
}
let mut result_path: Vec<&Room> = Vec::new();
if !parents.contains_key(end_room_name) { return Ok(None); }
let mut curr: &str = end_room_name;
let curr_as_room: &Room = self.get_room(curr).unwrap();
result_path.push(curr_as_room);
while parents.contains_key(curr) {
let parent: &String = parents.get(curr).unwrap();
let parent_as_room: &Room = self.get_room(parent).unwrap();
curr = parents.get(curr).unwrap().as_str();
result_path.push(parent_as_room);
}
result_path.reverse();
Ok(Some(result_path))
}
}
// TESTS DESCRIPTION
// test_basic[1..3] -> given;
// own_tests_test[1..10] -> invalid reader object passed, all should panic
// own_tests_test[11..] -> functionalities & несполучлив опит за error type check
#[test]
fn test_basic_1() {
let mut dungeon = Dungeon::new();
dungeon.add_room("Entrance").unwrap();
dungeon.add_room("Hallway").unwrap();
dungeon.set_link("Entrance", Direction::East, "Hallway").unwrap();
assert_eq!(dungeon.get_room("Entrance").unwrap().name, "Entrance");
assert_eq!(dungeon.get_next_room("Entrance", Direction::East).unwrap().unwrap().name, "Hallway");
}
#[allow(unused)]
const TEST_INPUT_1: &str = "
## Rooms
- Entrance
- Hallway
## Links
- Entrance -> East -> Hallway
";
#[test]
fn test_basic_2() {
// .trim() за да премахнем първия и последния ред:
let dungeon = Dungeon::from_reader(TEST_INPUT_1.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("Entrance").unwrap().name, "Entrance");
assert_eq!(dungeon.get_room("Hallway").unwrap().name, "Hallway");
assert_eq!(dungeon.get_next_room("Entrance", Direction::East).unwrap().unwrap().name, "Hallway");
}
#[test]
fn test_basic_3() {
let mut dungeon = Dungeon::new();
dungeon.add_room("Entrance").unwrap();
dungeon.add_room("Treasure Room").unwrap();
dungeon.set_link("Entrance", Direction::West, "Treasure Room").unwrap();
let path = dungeon.find_path("Entrance", "Treasure Room").unwrap().unwrap();
assert!(path.len() > 0);
}
#[allow(unused)]
const OWN_TESTS_INPUT_1: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
fn own_tests_test_1() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_1.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_2: &str = "
##Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_2() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_2.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_3: &str = "
## Rooms
- 1
- 2
##Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_3() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_3.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_4: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West-> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_4() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_4.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_5: &str = "
## Links
- 1 -> West -> 2
- 2 -> South -> 1
## Rooms
- 1
- 2
";
#[test]
#[should_panic]
fn own_tests_test_5() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_5.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_6: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South:) -> 1
";
#[test]
#[should_panic]
fn own_tests_test_6() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_6.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_7: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_7() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_7.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_8: &str = "
## Rooms
- 1
- 2
## Rooms
- 3
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_8() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_8.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_9: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> East -> 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_9() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_9.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_10: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_10() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_10.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_11: &str = "
## Rooms
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
## Links
- 1 -> East -> 2
- 10 -> West -> 6
- 9 -> North -> 6
- 3 -> North -> 8
- 4 -> South -> 8
- 4 -> East -> 7
- 7 -> South -> 2
- 5 -> East -> 9
- 5 -> North -> 3
";
#[test]
fn own_tests_test_11() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_11.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
assert_eq!(dungeon.get_room("2").unwrap().name, "2");
assert_eq!(dungeon.get_room("10").unwrap().name, "10");
let result_path = dungeon.find_path("1", "10").unwrap().unwrap();
let mut rooms: Vec<String> = Vec::new();
for room in result_path {
rooms.push(room.name.to_string());
}
assert_eq!(rooms, vec!["1", "2", "7", "4", "8", "3", "5", "9", "6", "10"]);
/*
4------7
| |
8\1#---2/10#
| |
3 6
| |
5---------9
*/
}
#[allow(unused)]
const OWN_TESTS_INPUT_12: &str = "
## Rooms
- 1
- 2
- 3
## Links
- 1 -> West -> 2
- 2 -> East -> 3
";
#[test]
fn own_tests_test_12() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_12.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
assert_eq!(dungeon.get_room("2").unwrap().name, "2");
assert_eq!(dungeon.get_room("3").unwrap().name, "3");
assert_eq!(dungeon.get_next_room("1", Direction::West).unwrap().unwrap().name, "2");
assert_eq!(dungeon.get_next_room("2", Direction::East).unwrap().unwrap().name, "3");
let result_path = dungeon.find_path("1", "3").unwrap().unwrap();
let mut rooms: Vec<String> = Vec::new();
for room in result_path {
rooms.push(room.name.to_string());
}
assert_eq!(rooms, vec!["1", "2", "3"]);
}
#[test]
fn own_tests_test_13() {
let mut dungeon = Dungeon::new();
dungeon.add_room("1").unwrap();
dungeon.add_room("2").unwrap();
dungeon.add_room("3").unwrap();
dungeon.add_room("4").unwrap();
dungeon.add_room("5").unwrap();
dungeon.add_room("6").unwrap();
dungeon.add_room("A").unwrap();
dungeon.add_room("B").unwrap();
dungeon.add_room("C").unwrap();
dungeon.add_room("D").unwrap();
dungeon.add_room("кирилица").unwrap();
dungeon.add_room("¥«¾ÈÚñüÿ").unwrap();
assert_eq!(dungeon.get_room("2").unwrap().name, "2");
assert_eq!(dungeon.get_room("A").unwrap().name, "A");
assert_eq!(dungeon.get_room("кирилица").unwrap().name, "кирилица");
assert_eq!(dungeon.get_room("¥«¾ÈÚñüÿ").unwrap().name, "¥«¾ÈÚñüÿ");
dungeon.set_link("1", Direction::West, "2").unwrap();
dungeon.set_link("2", Direction::North, "3").unwrap();
dungeon.set_link("3", Direction::East, "4").unwrap();
dungeon.set_link("4", Direction::South, "5").unwrap();
dungeon.set_link("6", Direction::East, "5").unwrap();
assert_eq!(dungeon.get_next_room("A", Direction::North).unwrap().is_none(), true);
assert_eq!(dungeon.get_next_room("3", Direction::North).unwrap().is_none(), true);
assert_eq!(dungeon.get_next_room("1", Direction::West).unwrap().unwrap().name, "2");
assert_eq!(dungeon.get_next_room("4", Direction::West).unwrap().unwrap().name, "3");
assert_eq!(dungeon.get_next_room("4", Direction::South).unwrap().unwrap().name, "5");
let result_path = dungeon.find_path("1", "6").unwrap().unwrap();
let mut names: Vec<String> = Vec::new();
for room in result_path {
names.push(room.name.to_string());
}
assert_eq!(names, vec!["1", "2", "3", "4", "5", "6"]);
}
#[test]
fn own_tests_test_14() {
let mut dungeon = Dungeon::new();
dungeon.add_room("1").unwrap();
dungeon.add_room("2").unwrap();
dungeon.add_room("3").unwrap();
// иска PartialEq на Errors, а не може, понеже имаме std::io::Error ?
// let should_err = dungeon.add_room("1").unwrap_err();
// assert_eq!(should_err, Err(Errors::DuplicateRoom("1".to_string())).unwrap_err());
// ||
// if let Err(e) = dungeon.add_room("1") {
// assert_eq!(e, Errors::DuplicateRoom("1".to_string()));
// }
dungeon.set_link("1", Direction::West, "2").unwrap();
dungeon.set_link("2", Direction::North, "3").unwrap();
}
Александър качи решение на 10.01.2022 19:44 (преди над 3 години)
use std::collections::VecDeque;
use std::collections::HashMap;
use std::io::BufRead;
#[derive(Debug)]
pub enum Errors {
DuplicateRoom(String),
UnknownRoom(String),
IoError(std::io::Error),
LineParseError { line_number: usize },
DirectionParseError(String),
}
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
pub enum Direction {
North,
South,
East,
West,
}
pub struct Room {
pub name: String,
// може би по-добра идея е
// neigh_E: String,
// neigh_W: String, ... (или масив от 4 стринга с конвенция [0] <=> E, [1] <=> W, ...)
pub neighs: HashMap<Direction, String>,
}
pub struct Dungeon {
pub rooms: HashMap<String, Room>,
}
impl Dungeon {
pub fn new() -> Self {
Self {
rooms: HashMap::new(),
}
}
pub fn add_room(&mut self, name: &str) -> Result<(), Errors> {
if self.rooms.contains_key(name) {
Err(Errors::DuplicateRoom(name.to_string()))
} else {
self.rooms.insert(
name.to_string(),
Room {
name: name.to_string(),
neighs: HashMap::new(),
},
);
Ok(())
}
}
pub fn get_room(&self, room_name: &str) -> Result<&Room, Errors> {
if self.rooms.contains_key(room_name) {
Ok(self.rooms.get(room_name).unwrap())
} else {
Err(Errors::UnknownRoom(room_name.to_string()))
}
}
pub fn set_link(&mut self, room_name: &str, direction: Direction, other_room_name: &str) -> Result<(), Errors> {
if self.rooms.contains_key(room_name) {
if self.rooms.contains_key(other_room_name) {
// добавяме 'room -> dir -> other'
self.rooms.get_mut(room_name).unwrap().neighs.insert(direction, other_room_name.to_string());
let reverse: Direction = match direction {
Direction::North => Direction::South,
Direction::South => Direction::North,
Direction::East => Direction::West,
Direction::West => Direction::East,
};
// добавяме 'other -> reverse_dir -> room'
self.rooms.get_mut(other_room_name).unwrap().neighs.insert(reverse, room_name.to_string());
Ok(())
} else {
Err(Errors::UnknownRoom(other_room_name.to_string()))
}
} else {
Err(Errors::UnknownRoom(room_name.to_string()))
}
}
pub fn get_next_room(&self, room_name: &str, direction: Direction) -> Result<Option<&Room>, Errors> {
if self.rooms.contains_key(room_name) {
if self.rooms.get(room_name).unwrap().neighs.contains_key(&direction) {
let neigh_as_str: &String = self.rooms.get(room_name).unwrap().neighs.get(&direction).unwrap();
let neigh_as_room: &Room = self.rooms.get(neigh_as_str).unwrap();
Ok(Some(neigh_as_room))
} else {
Ok(None)
}
} else {
Err(Errors::UnknownRoom(room_name.to_string()))
}
}
pub fn from_reader<B: BufRead>(reader: B) -> Result<Self, Errors> {
let mut line: String = String::new();
let mut reader: B = reader;
let mut line_number: usize = 0;
let mut dungeon: Dungeon = Dungeon::new();
let mut order: [bool; 3] = [false, false, false]; // [0] <=> "## Rooms", [1] <=> "\n", [2] <=> "## Links"
while reader.read_line(&mut line).unwrap() > 0 {
// Rooms header
if line_number == 0 {
if line == "## Rooms\n" {
order[0] = true;
} else {
return Err(Errors::IoError(Ok(line).err().unwrap()));
}
}
// New line b/w rooms and links
else if line == "\n" && order[0] && !order[1] && !order[2] {
order[1] = true;
}
// Links header
else if line == "## Links\n" && order[0] && order[1] && !order[2] {
order[2] = true;
}
// data row
else if line.starts_with("- ") {
// format <=> "- <room>"
if order[0] && !order[1] && !order[2] {
line.replace_range(0..2, "");
let mut room: String = line.clone();
room.pop().unwrap();
dungeon.add_room(room.as_str())?;
}
// format <=> "- <room> -> <dir> -> <other_room>"
else if line.matches(" -> ").count() == 2 && order[0] && order[1] && order[2] {
line.replace_range(0..2, "");
let last_char: char = line.pop().unwrap();
// eventually ще стигнем до последния link ред, който не завършва на \n
if last_char != '\n' { line.push(last_char); }
let words: Vec<&str> = line.split_terminator(" -> ").collect();
let room: &str = words.get(0).unwrap();
let dir: &str = words.get(1).unwrap();
let other_room: &str = words.get(2).unwrap();
let dir: Direction = match dir {
"North" => Direction::North,
"South" => Direction::South,
"East" => Direction::East,
"West" => Direction::West,
_ => return Err(Errors::DirectionParseError(dir.to_string()))
};
dungeon.set_link(room, dir, other_room)?;
+ } else {
+ return Err(Errors::LineParseError { line_number });
}
-
- else {
- return Err(Errors::LineParseError {line_number});
- }
+ } else {
+ return Err(Errors::LineParseError { line_number });
}
-
- else {
- return Err(Errors::LineParseError {line_number});
- }
line_number += 1;
line.clear();
}
Ok(dungeon)
}
pub fn find_path(&self, start_room_name: &str, end_room_name: &str) -> Result<Option<Vec<&Room>>, Errors> {
+ if self.get_room(start_room_name).is_err() {
+ return Err(Errors::UnknownRoom(start_room_name.to_string()));
+ } else if self.get_room(end_room_name).is_err() {
+ return Err(Errors::UnknownRoom(end_room_name.to_string()));
+ };
+
let mut rooms: VecDeque<String> = VecDeque::new();
let mut visited: HashMap<String, bool> = HashMap::new(); // visited[room_str] = true/false
let mut parents: HashMap<String, String> = HashMap::new(); // parents[room_str] = parent_str
rooms.push_front(start_room_name.to_string());
visited.insert(start_room_name.to_string(), true);
while !rooms.is_empty() {
let curr: String = rooms.pop_back().unwrap().clone();
if curr == end_room_name { break; }
for (_direction, neigh) in self.rooms.get(&curr).unwrap().neighs.iter() {
if !visited.contains_key(&neigh.clone()) {
parents.insert(neigh.clone(), curr.clone());
visited.insert(neigh.clone(), true);
rooms.push_front(neigh.to_string());
}
}
}
let mut result_path: Vec<&Room> = Vec::new();
if !parents.contains_key(end_room_name) { return Ok(None); }
let mut curr: &str = end_room_name;
let curr_as_room: &Room = self.get_room(curr).unwrap();
result_path.push(curr_as_room);
while parents.contains_key(curr) {
let parent: &String = parents.get(curr).unwrap();
let parent_as_room: &Room = self.get_room(parent).unwrap();
curr = parents.get(curr).unwrap().as_str();
result_path.push(parent_as_room);
}
result_path.reverse();
Ok(Some(result_path))
}
}
// TESTS DESCRIPTION
// test_basic[1..3] -> given;
// own_tests_test[1..10] -> invalid reader object passed, all should panic
// own_tests_test[11..] -> functionalities & несполучлив опит за error type check
#[test]
fn test_basic_1() {
let mut dungeon = Dungeon::new();
dungeon.add_room("Entrance").unwrap();
dungeon.add_room("Hallway").unwrap();
dungeon.set_link("Entrance", Direction::East, "Hallway").unwrap();
assert_eq!(dungeon.get_room("Entrance").unwrap().name, "Entrance");
assert_eq!(dungeon.get_next_room("Entrance", Direction::East).unwrap().unwrap().name, "Hallway");
}
#[allow(unused)]
const TEST_INPUT_1: &str = "
## Rooms
- Entrance
- Hallway
## Links
- Entrance -> East -> Hallway
";
#[test]
fn test_basic_2() {
// .trim() за да премахнем първия и последния ред:
let dungeon = Dungeon::from_reader(TEST_INPUT_1.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("Entrance").unwrap().name, "Entrance");
assert_eq!(dungeon.get_room("Hallway").unwrap().name, "Hallway");
assert_eq!(dungeon.get_next_room("Entrance", Direction::East).unwrap().unwrap().name, "Hallway");
}
#[test]
fn test_basic_3() {
let mut dungeon = Dungeon::new();
dungeon.add_room("Entrance").unwrap();
dungeon.add_room("Treasure Room").unwrap();
dungeon.set_link("Entrance", Direction::West, "Treasure Room").unwrap();
let path = dungeon.find_path("Entrance", "Treasure Room").unwrap().unwrap();
assert!(path.len() > 0);
}
#[allow(unused)]
const OWN_TESTS_INPUT_1: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
fn own_tests_test_1() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_1.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_2: &str = "
##Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_2() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_2.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_3: &str = "
## Rooms
- 1
- 2
##Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_3() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_3.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_4: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West-> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_4() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_4.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_5: &str = "
## Links
- 1 -> West -> 2
- 2 -> South -> 1
## Rooms
- 1
- 2
";
#[test]
#[should_panic]
fn own_tests_test_5() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_5.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_6: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South:) -> 1
";
#[test]
#[should_panic]
fn own_tests_test_6() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_6.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_7: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_7() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_7.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_8: &str = "
## Rooms
- 1
- 2
## Rooms
- 3
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_8() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_8.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_9: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> East -> 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_9() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_9.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_10: &str = "
## Rooms
- 1
- 2
## Links
- 1 -> West -> 2
- 2 -> South -> 1
";
#[test]
#[should_panic]
fn own_tests_test_10() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_10.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
}
#[allow(unused)]
const OWN_TESTS_INPUT_11: &str = "
## Rooms
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
## Links
- 1 -> East -> 2
- 10 -> West -> 6
- 9 -> North -> 6
- 3 -> North -> 8
- 4 -> South -> 8
- 4 -> East -> 7
- 7 -> South -> 2
- 5 -> East -> 9
- 5 -> North -> 3
";
#[test]
fn own_tests_test_11() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_11.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
assert_eq!(dungeon.get_room("2").unwrap().name, "2");
assert_eq!(dungeon.get_room("10").unwrap().name, "10");
let result_path = dungeon.find_path("1", "10").unwrap().unwrap();
let mut rooms: Vec<String> = Vec::new();
for room in result_path {
rooms.push(room.name.to_string());
}
assert_eq!(rooms, vec!["1", "2", "7", "4", "8", "3", "5", "9", "6", "10"]);
/*
4------7
| |
8\1#---2/10#
| |
3 6
| |
5---------9
*/
}
#[allow(unused)]
const OWN_TESTS_INPUT_12: &str = "
## Rooms
- 1
- 2
- 3
## Links
- 1 -> West -> 2
- 2 -> East -> 3
";
#[test]
fn own_tests_test_12() {
let dungeon: Dungeon = Dungeon::from_reader(OWN_TESTS_INPUT_12.trim().as_bytes()).unwrap();
assert_eq!(dungeon.get_room("1").unwrap().name, "1");
assert_eq!(dungeon.get_room("2").unwrap().name, "2");
assert_eq!(dungeon.get_room("3").unwrap().name, "3");
assert_eq!(dungeon.get_next_room("1", Direction::West).unwrap().unwrap().name, "2");
assert_eq!(dungeon.get_next_room("2", Direction::East).unwrap().unwrap().name, "3");
let result_path = dungeon.find_path("1", "3").unwrap().unwrap();
let mut rooms: Vec<String> = Vec::new();
for room in result_path {
rooms.push(room.name.to_string());
}
assert_eq!(rooms, vec!["1", "2", "3"]);
}
#[test]
fn own_tests_test_13() {
let mut dungeon = Dungeon::new();
dungeon.add_room("1").unwrap();
dungeon.add_room("2").unwrap();
dungeon.add_room("3").unwrap();
dungeon.add_room("4").unwrap();
dungeon.add_room("5").unwrap();
dungeon.add_room("6").unwrap();
dungeon.add_room("A").unwrap();
dungeon.add_room("B").unwrap();
dungeon.add_room("C").unwrap();
dungeon.add_room("D").unwrap();
dungeon.add_room("кирилица").unwrap();
dungeon.add_room("¥«¾ÈÚñüÿ").unwrap();
assert_eq!(dungeon.get_room("2").unwrap().name, "2");
assert_eq!(dungeon.get_room("A").unwrap().name, "A");
assert_eq!(dungeon.get_room("кирилица").unwrap().name, "кирилица");
assert_eq!(dungeon.get_room("¥«¾ÈÚñüÿ").unwrap().name, "¥«¾ÈÚñüÿ");
dungeon.set_link("1", Direction::West, "2").unwrap();
dungeon.set_link("2", Direction::North, "3").unwrap();
dungeon.set_link("3", Direction::East, "4").unwrap();
dungeon.set_link("4", Direction::South, "5").unwrap();
dungeon.set_link("6", Direction::East, "5").unwrap();
assert_eq!(dungeon.get_next_room("A", Direction::North).unwrap().is_none(), true);
assert_eq!(dungeon.get_next_room("3", Direction::North).unwrap().is_none(), true);
assert_eq!(dungeon.get_next_room("1", Direction::West).unwrap().unwrap().name, "2");
assert_eq!(dungeon.get_next_room("4", Direction::West).unwrap().unwrap().name, "3");
assert_eq!(dungeon.get_next_room("4", Direction::South).unwrap().unwrap().name, "5");
let result_path = dungeon.find_path("1", "6").unwrap().unwrap();
let mut names: Vec<String> = Vec::new();
for room in result_path {
names.push(room.name.to_string());
}
assert_eq!(names, vec!["1", "2", "3", "4", "5", "6"]);
}
#[test]
fn own_tests_test_14() {
let mut dungeon = Dungeon::new();
dungeon.add_room("1").unwrap();
dungeon.add_room("2").unwrap();
dungeon.add_room("3").unwrap();
// иска PartialEq на Errors, а не може, понеже имаме std::io::Error ?
// let should_err = dungeon.add_room("1").unwrap_err();
// assert_eq!(should_err, Err(Errors::DuplicateRoom("1".to_string())).unwrap_err());
// ||
// if let Err(e) = dungeon.add_room("1") {
// assert_eq!(e, Errors::DuplicateRoom("1".to_string()));
// }
dungeon.set_link("1", Direction::West, "2").unwrap();
dungeon.set_link("2", Direction::North, "3").unwrap();
}