Решение на Dungeons and Compilers от Виктор Терзиев

Обратно към всички решения

Към профила на Виктор Терзиев

Резултати

  • 19 точки от тестове
  • 0 бонус точки
  • 19 точки общо
  • 14 успешни тест(а)
  • 1 неуспешни тест(а)

Код

use std::hash::Hash;
use std::io::BufRead;
use std::collections::{HashMap, VecDeque};
/// Различните грешки, които ще очакваме да върнете като резултат от някои невалидни операции.
/// Повече детайли по-долу.
///
#[derive(Debug)]
pub enum Errors {
DuplicateRoom(String),
UnknownRoom(String),
IoError(std::io::Error),
LineParseError { line_number: usize },
DirectionParseError(String),
}
/// Четирите посоки, в които може една стая да има съседи. Може да добавите още trait
/// имплементации, за да си улесните живота.
///
#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)]
pub enum Direction {
North,
South,
East,
West,
}
fn opposite(direction: Direction)-> Direction {
return match direction {
Direction::South => Direction::North,
Direction::North => Direction::South,
Direction::East => Direction::West,
Direction::West => Direction::East
};
}
/// Една стая в подземията. Дефинира се само с име, макар че в по-интересна имплементация може да
/// държи item-и, противници...
///
#[derive(Debug, PartialEq, Eq)]
pub struct Room {
pub name: String,
// Каквито други полета ви трябват
pub in_direction: HashMap<Direction, String>
}
impl Room {
pub fn new(cname: &str) -> Self {
Room {
name: cname.clone().to_string(),
in_direction: HashMap::new()
}
}
pub fn get_next_room(&self, direction: Direction) -> Option<String> {
if self.in_direction.contains_key(&direction) {
let nxt_room = self.in_direction.get(&direction);
Some(nxt_room.unwrap().clone())
} else {
None
}
}
pub fn set_link(
&mut self,
direction: Direction,
other_room_name: &str,
) {
self.in_direction.insert(direction, other_room_name.to_string());
}
}
/// Контейнер за стаите и не само. Ще работим предимно със тази структура.
///
pub struct Dungeon {
rooms: HashMap<String, Room>
// Каквито полета ви трябват
}
impl Dungeon {
/// Конструиране на празен Dungeon, в който няма никакви стаи.
///
pub fn new() -> Self {
Dungeon {
rooms: HashMap::new()
}
}
/// Добавяне на стая към Dungeon с име `name`. Връща `Ok(())` при успех. Ако вече има стая с
/// такова име, очакваме да върнете `Errors::DuplicateRoom` с името.
///
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::new(name));
Ok(())
}
}
/// Прочитане на дадена стая -- когато извикаме `get_room`, очакваме reference към `Room`
/// структурата с това име.
///
/// Ако няма такава стая, очакваме `Errors::UnknownRoom` с подаденото име.
///
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()))
}
}
/// Добавяне на съсед на дадена стая. След извикването на функцията, очакваме стаята с име
/// `room_name` да има връзка в посока `direction` със стаята с име `other_room_name`.
///
/// Също така очакваме `other_room_name` да има връзка с `room_name` в *обратната* посока.
///
/// Успешен резултат е `Ok(())`. В случай, че която от двете стаи не същестува, очакваме грешка
/// `Errors::UnknownRoom` със съответното име на липсваща стая. Ако и двете липсват, спокойно
/// върнете тази, която проверявате първо.
///
pub fn set_link(
&mut self,
room_name: &str,
direction: Direction,
other_room_name: &str,
) -> Result<(), Errors> {
if !self.rooms.contains_key(room_name) {
Err(Errors::UnknownRoom(room_name.to_string()))
} else if !self.rooms.contains_key(other_room_name) {
Err(Errors::UnknownRoom(other_room_name.to_string()))
} else {
self.rooms.get_mut(room_name).unwrap().set_link(direction, other_room_name);
let op = opposite(direction);
if !self.rooms.get(other_room_name).unwrap().in_direction.contains_key(&op) {
self.set_link(other_room_name, op, room_name);
}
Ok(())
}
}
/// Четене на съседа на стаята с име `room_name` в посока `direction`. Тук има няколко
/// варианта на изход:
///
/// - Ако подадената стая не съществува, очакваме грешка `Errors::UnknownRoom`
/// - Ако подадената стая няма съсед в тази посока, Ok(None) е смисления резултат
/// - Иначе, чакаме reference към `Room` структурата на въпросния съсед, опакована в `Ok(Some(`.
///
pub fn get_next_room(&self, room_name: &str, direction: Direction) -> Result<Option<&Room>, Errors> {
if !self.rooms.contains_key(room_name) {
Err(Errors::UnknownRoom(room_name.to_string()))
} else {
let next_room_name = self.rooms.get(room_name).unwrap().get_next_room(direction);
println!("Next room name: {:?}", next_room_name);
if next_room_name.is_none() {
return Ok(None);
} else {
return Ok(self.rooms.get(&next_room_name.unwrap()));
}
}
}
}
impl Dungeon {
/// Прочитаме структурата на dungeon от нещо, което имплементира `BufRead`. Това може да е
/// файл, или, ако тестваме, може да е просто колекция от байтове.
///
/// Успешен резултат връща новосъздадения dungeon, пакетиран в `Ok`.
///
/// Вижте по-долу за обяснение на грешките, които очакваме.
///
pub fn from_reader<B: BufRead>(reader: B) -> Result<Self, Errors> {
let mut d = Dungeon::new();
let mut readRoomsStart = true;
let mut readingRooms = false;
let mut readLinksStart = false;
let mut readingLinks = false;
let mut isEmpty = true;
let mut index = 0;
for l in reader.lines().enumerate() {
isEmpty = false;
if l.1.is_err() {
return Err(Errors::IoError(l.1.err().unwrap()))
} else {
let line = l.1.ok().unwrap();
let line = line.trim();
index = l.0+1;
println!("processing line {} {} ", line, index);
println!("processing line {} {} ", line, index);
if readRoomsStart { // the line should be ## Rooms
if match_prefix( "## Rooms", &line).is_none() {
return Err(Errors::LineParseError{ line_number: index});
}
readRoomsStart = false;
readingRooms = true;
} else if readingRooms {
let res = match_prefix("- ", &line);
println!("reading rooms: {:?} ", res);
if res.is_none() {
if line != "" {
return Err(Errors::LineParseError{ line_number: index});
} else {
readingRooms = false;
readLinksStart = true;
}
} else {
let r= d.add_room(res.unwrap());
if r.is_err() {
return Err(r.err().unwrap());
}
}
} else if readLinksStart {
if match_prefix("## Links", &line).is_none() {
return Err(Errors::LineParseError{ line_number: index});
} else {
readLinksStart = false;
readingLinks = true;
}
} else if readingLinks {
let res = match_prefix("- ", &line);
println!("Reading links {:?}", res);
if res.is_none() {
break;
} else {
let k: Vec<&str> = res.unwrap().split(" -> ").collect();
println!("Reading links splitted {:?}", k);
if k.len() != 3 {
return Err(Errors::LineParseError{ line_number: index });
}
let dir = match k.get(1) {
Some(&"North") => Some(Direction::North),
Some(&"South") => Some(Direction::South),
Some(&"East") => Some(Direction::East),
Some(&"West") => Some(Direction::West),
_ => None
};
println!("Reading links dir: {:?}", dir);
if dir.is_none() {
return Err(Errors::DirectionParseError(k.get(1).unwrap().to_string()));
}
let kk = d.set_link(k.get(0).unwrap(), dir.unwrap(), k.get(2).unwrap());
println!("setting link result: {:?}", kk);
if kk.is_err() {
return Err(kk.err().unwrap());
}
}
}
}
}
if isEmpty {
return Err(Errors::LineParseError{ line_number: 0});
}
if !readingLinks {
return Err(Errors::LineParseError{ line_number: index});
}
return Ok(d);
}
}
/// match_prefix("- ", "- Foo") //=> Some("Foo")
/// match_prefix("- ", "Bar") //=> None
///
fn match_prefix<'a, 'b>(prefix: &'a str, input: &'b str) -> Option<&'b str> {
return input.strip_prefix(prefix);
}
impl Dungeon {
/// Търси път от `start_room_name` до `end_room_name` и го връща във вектор, пакетиран във
/// `Ok(Some(` ако намери.
///
/// Ако няма път между тези две стаи, връща `Ok(None)`.
///
/// Ако четенето на стаи в един момент върне грешка, очакваме да върнете грешката нагоре.
///
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(self.get_room(start_room_name).err().unwrap());
}
let mut previous = HashMap::new();
let mut q = VecDeque::new();
q.push_back(start_room_name);
previous.insert(start_room_name.to_string(), start_room_name);
while !q.is_empty() {
let crr = q.pop_front().unwrap();
if let Ok(Some(next_room)) = self.get_next_room(crr, Direction::East) {
if !previous.contains_key(&next_room.name) {
previous.insert(next_room.name.to_string(), crr);
q.push_back(next_room.name.as_str());
}
}
if let Ok(Some(next_room)) = self.get_next_room(crr, Direction::West) {
if !previous.contains_key(&next_room.name) {
previous.insert(next_room.name.to_string(), crr);
q.push_back(next_room.name.as_str());
}
}
if let Ok(Some(next_room)) = self.get_next_room(crr, Direction::North) {
if !previous.contains_key(&next_room.name) {
previous.insert(next_room.name.to_string(), crr);
q.push_back(next_room.name.as_str());
}
}
if let Ok(Some(next_room)) = self.get_next_room(crr, Direction::South) {
if !previous.contains_key(&next_room.name) {
previous.insert(next_room.name.to_string(), crr);
q.push_back(next_room.name.as_str());
}
}
}
if !previous.contains_key(end_room_name) {
return Ok(None);
}
let mut c = end_room_name;
let mut ans = Vec::new();
while previous.get(c).unwrap() != &c {
ans.push(self.get_room(c).unwrap());
c = previous.get(c).unwrap();
}
ans.push(self.get_room(c).unwrap());
ans.reverse();
return Ok(Some(ans));
}
}

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20220116-3533338-wre3jv/solution)
warning: unused `Result` that must be used
   --> src/lib.rs:138:17
    |
138 |                 self.set_link(other_room_name, op, room_name);                
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(unused_must_use)]` on by default
    = note: this `Result` may be an `Err` variant, which should be handled

warning: variable `readRoomsStart` should have a snake case name
   --> src/lib.rs:177:17
    |
177 |         let mut readRoomsStart = true;
    |                 ^^^^^^^^^^^^^^ help: convert the identifier to snake case: `read_rooms_start`
    |
    = note: `#[warn(non_snake_case)]` on by default

warning: variable `readingRooms` should have a snake case name
   --> src/lib.rs:178:17
    |
178 |         let mut readingRooms = false;
    |                 ^^^^^^^^^^^^ help: convert the identifier to snake case: `reading_rooms`

warning: variable `readLinksStart` should have a snake case name
   --> src/lib.rs:179:17
    |
179 |         let mut readLinksStart = false;
    |                 ^^^^^^^^^^^^^^ help: convert the identifier to snake case: `read_links_start`

warning: variable `readingLinks` should have a snake case name
   --> src/lib.rs:180:17
    |
180 |         let mut readingLinks = false;
    |                 ^^^^^^^^^^^^ help: convert the identifier to snake case: `reading_links`

warning: variable `isEmpty` should have a snake case name
   --> src/lib.rs:181:17
    |
181 |         let mut isEmpty = true;
    |                 ^^^^^^^ help: convert the identifier to snake case: `is_empty`

warning: `solution` (lib) generated 6 warnings
    Finished test [unoptimized + debuginfo] target(s) in 5.41s
     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 ... ok
test solution_test::test_finding_an_indirect_path ... ok
test solution_test::test_finding_no_path ... FAILED
test solution_test::test_invalid_parsing ... ok
test solution_test::test_io_error ... ok
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 ... ok
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_no_path stdout ----
Next room name: None
Next room name: None
Next room name: None
Next room name: None
Next room name: None
Next room name: None
Next room name: None
Next room name: None
thread '<unnamed>' panicked at 'assertion failed: path.is_err()', tests/solution_test.rs:382:9
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:372:5


failures:
    solution_test::test_finding_no_path

test result: FAILED. 14 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass '--test solution_test'

История (2 версии и 0 коментара)

Виктор качи първо решение на 03.01.2022 20:59 (преди почти 4 години)

Виктор качи решение на 11.01.2022 15:15 (преди над 3 години)

use std::hash::Hash;
use std::io::BufRead;
use std::collections::{HashMap, VecDeque};
/// Различните грешки, които ще очакваме да върнете като резултат от някои невалидни операции.
/// Повече детайли по-долу.
///
#[derive(Debug)]
pub enum Errors {
DuplicateRoom(String),
UnknownRoom(String),
IoError(std::io::Error),
LineParseError { line_number: usize },
DirectionParseError(String),
}
/// Четирите посоки, в които може една стая да има съседи. Може да добавите още trait
/// имплементации, за да си улесните живота.
///
#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)]
pub enum Direction {
North,
South,
East,
West,
}
fn opposite(direction: Direction)-> Direction {
return match direction {
Direction::South => Direction::North,
Direction::North => Direction::South,
Direction::East => Direction::West,
Direction::West => Direction::East
};
}
/// Една стая в подземията. Дефинира се само с име, макар че в по-интересна имплементация може да
/// държи item-и, противници...
///
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq)]
pub struct Room {
pub name: String,
// Каквито други полета ви трябват
pub in_direction: HashMap<Direction, String>
}
impl Room {
pub fn new(cname: &str) -> Self {
Room {
name: cname.clone().to_string(),
in_direction: HashMap::new()
}
}
pub fn get_next_room(&self, direction: Direction) -> Option<String> {
if self.in_direction.contains_key(&direction) {
let nxt_room = self.in_direction.get(&direction);
Some(nxt_room.unwrap().clone())
} else {
None
}
}
pub fn set_link(
&mut self,
direction: Direction,
other_room_name: &str,
) {
self.in_direction.insert(direction, other_room_name.to_string());
}
}
/// Контейнер за стаите и не само. Ще работим предимно със тази структура.
///
pub struct Dungeon {
rooms: HashMap<String, Room>
// Каквито полета ви трябват
}
impl Dungeon {
/// Конструиране на празен Dungeon, в който няма никакви стаи.
///
pub fn new() -> Self {
Dungeon {
rooms: HashMap::new()
}
}
/// Добавяне на стая към Dungeon с име `name`. Връща `Ok(())` при успех. Ако вече има стая с
/// такова име, очакваме да върнете `Errors::DuplicateRoom` с името.
///
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::new(name));
Ok(())
}
}
/// Прочитане на дадена стая -- когато извикаме `get_room`, очакваме reference към `Room`
/// структурата с това име.
///
/// Ако няма такава стая, очакваме `Errors::UnknownRoom` с подаденото име.
///
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()))
}
}
/// Добавяне на съсед на дадена стая. След извикването на функцията, очакваме стаята с име
/// `room_name` да има връзка в посока `direction` със стаята с име `other_room_name`.
///
/// Също така очакваме `other_room_name` да има връзка с `room_name` в *обратната* посока.
///
/// Успешен резултат е `Ok(())`. В случай, че която от двете стаи не същестува, очакваме грешка
/// `Errors::UnknownRoom` със съответното име на липсваща стая. Ако и двете липсват, спокойно
/// върнете тази, която проверявате първо.
///
pub fn set_link(
&mut self,
room_name: &str,
direction: Direction,
other_room_name: &str,
) -> Result<(), Errors> {
if !self.rooms.contains_key(room_name) {
Err(Errors::UnknownRoom(room_name.to_string()))
} else if !self.rooms.contains_key(other_room_name) {
Err(Errors::UnknownRoom(other_room_name.to_string()))
} else {
self.rooms.get_mut(room_name).unwrap().set_link(direction, other_room_name);
let op = opposite(direction);
if !self.rooms.get(other_room_name).unwrap().in_direction.contains_key(&op) {
self.set_link(other_room_name, op, room_name);
}
Ok(())
}
}
/// Четене на съседа на стаята с име `room_name` в посока `direction`. Тук има няколко
/// варианта на изход:
///
/// - Ако подадената стая не съществува, очакваме грешка `Errors::UnknownRoom`
/// - Ако подадената стая няма съсед в тази посока, Ok(None) е смисления резултат
/// - Иначе, чакаме reference към `Room` структурата на въпросния съсед, опакована в `Ok(Some(`.
///
pub fn get_next_room(&self, room_name: &str, direction: Direction) -> Result<Option<&Room>, Errors> {
if !self.rooms.contains_key(room_name) {
Err(Errors::UnknownRoom(room_name.to_string()))
} else {
let next_room_name = self.rooms.get(room_name).unwrap().get_next_room(direction);
println!("Next room name: {:?}", next_room_name);
if next_room_name.is_none() {
return Ok(None);
} else {
return Ok(self.rooms.get(&next_room_name.unwrap()));
}
}
}
}
impl Dungeon {
/// Прочитаме структурата на dungeon от нещо, което имплементира `BufRead`. Това може да е
/// файл, или, ако тестваме, може да е просто колекция от байтове.
///
/// Успешен резултат връща новосъздадения dungeon, пакетиран в `Ok`.
///
/// Вижте по-долу за обяснение на грешките, които очакваме.
///
pub fn from_reader<B: BufRead>(reader: B) -> Result<Self, Errors> {
let mut d = Dungeon::new();
let mut readRoomsStart = true;
let mut readingRooms = false;
let mut readLinksStart = false;
let mut readingLinks = false;
let mut isEmpty = true;
+ let mut index = 0;
for l in reader.lines().enumerate() {
isEmpty = false;
if l.1.is_err() {
return Err(Errors::IoError(l.1.err().unwrap()))
} else {
let line = l.1.ok().unwrap();
- let index = l.0+1;
+ let line = line.trim();
+ index = l.0+1;
println!("processing line {} {} ", line, index);
println!("processing line {} {} ", line, index);
if readRoomsStart { // the line should be ## Rooms
if match_prefix( "## Rooms", &line).is_none() {
return Err(Errors::LineParseError{ line_number: index});
}
readRoomsStart = false;
readingRooms = true;
} else if readingRooms {
let res = match_prefix("- ", &line);
println!("reading rooms: {:?} ", res);
if res.is_none() {
if line != "" {
return Err(Errors::LineParseError{ line_number: index});
} else {
readingRooms = false;
readLinksStart = true;
}
} else {
let r= d.add_room(res.unwrap());
if r.is_err() {
return Err(r.err().unwrap());
}
}
} else if readLinksStart {
if match_prefix("## Links", &line).is_none() {
return Err(Errors::LineParseError{ line_number: index});
} else {
readLinksStart = false;
readingLinks = true;
}
} else if readingLinks {
let res = match_prefix("- ", &line);
println!("Reading links {:?}", res);
if res.is_none() {
break;
} else {
let k: Vec<&str> = res.unwrap().split(" -> ").collect();
println!("Reading links splitted {:?}", k);
if k.len() != 3 {
return Err(Errors::LineParseError{ line_number: index });
}
let dir = match k.get(1) {
Some(&"North") => Some(Direction::North),
Some(&"South") => Some(Direction::South),
Some(&"East") => Some(Direction::East),
Some(&"West") => Some(Direction::West),
_ => None
};
println!("Reading links dir: {:?}", dir);
if dir.is_none() {
- return Err(Errors::LineParseError{ line_number: index });
+ return Err(Errors::DirectionParseError(k.get(1).unwrap().to_string()));
}
let kk = d.set_link(k.get(0).unwrap(), dir.unwrap(), k.get(2).unwrap());
println!("setting link result: {:?}", kk);
if kk.is_err() {
return Err(kk.err().unwrap());
}
}
}
}
}
if isEmpty {
return Err(Errors::LineParseError{ line_number: 0});
}
+ if !readingLinks {
+ return Err(Errors::LineParseError{ line_number: index});
+ }
return Ok(d);
}
}
/// match_prefix("- ", "- Foo") //=> Some("Foo")
/// match_prefix("- ", "Bar") //=> None
///
fn match_prefix<'a, 'b>(prefix: &'a str, input: &'b str) -> Option<&'b str> {
return input.strip_prefix(prefix);
}
impl Dungeon {
/// Търси път от `start_room_name` до `end_room_name` и го връща във вектор, пакетиран във
/// `Ok(Some(` ако намери.
///
/// Ако няма път между тези две стаи, връща `Ok(None)`.
///
/// Ако четенето на стаи в един момент върне грешка, очакваме да върнете грешката нагоре.
///
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(self.get_room(start_room_name).err().unwrap());
}
let mut previous = HashMap::new();
let mut q = VecDeque::new();
q.push_back(start_room_name);
previous.insert(start_room_name.to_string(), start_room_name);
while !q.is_empty() {
let crr = q.pop_front().unwrap();
if let Ok(Some(next_room)) = self.get_next_room(crr, Direction::East) {
if !previous.contains_key(&next_room.name) {
previous.insert(next_room.name.to_string(), crr);
q.push_back(next_room.name.as_str());
}
}
if let Ok(Some(next_room)) = self.get_next_room(crr, Direction::West) {
if !previous.contains_key(&next_room.name) {
previous.insert(next_room.name.to_string(), crr);
q.push_back(next_room.name.as_str());
}
}
if let Ok(Some(next_room)) = self.get_next_room(crr, Direction::North) {
if !previous.contains_key(&next_room.name) {
previous.insert(next_room.name.to_string(), crr);
q.push_back(next_room.name.as_str());
}
}
if let Ok(Some(next_room)) = self.get_next_room(crr, Direction::South) {
if !previous.contains_key(&next_room.name) {
previous.insert(next_room.name.to_string(), crr);
q.push_back(next_room.name.as_str());
}
}
}
if !previous.contains_key(end_room_name) {
return Ok(None);
}
let mut c = end_room_name;
let mut ans = Vec::new();
while previous.get(c).unwrap() != &c {
ans.push(self.get_room(c).unwrap());
c = previous.get(c).unwrap();
}
ans.push(self.get_room(c).unwrap());
ans.reverse();
return Ok(Some(ans));
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
- #[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");
- }
-
- const TEST_INPUT_1: &str = "
-## Rooms
-- Entrance
-- Hallway
-
-## Links
-- Entrance -> East -> Hallway
-- Entrance -> West -> 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");
- assert_eq!(dungeon.get_next_room("Entrance", Direction::West).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);
- println!("{:?}", path);
- }
-
-
- #[test]
- fn test_basic_4() {
- 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("Hallway").unwrap().name, "Hallway");
- assert_eq!(dungeon.get_next_room("Hallway", Direction::West).unwrap().unwrap().name, "Entrance");
- }
-
- #[test]
- fn test_basic_5() {
- let mut dungeon = Dungeon::new();
-
- dungeon.add_room("Entrance").unwrap();
- dungeon.add_room("Hallway").unwrap();
- dungeon.add_room("Magic Lab").unwrap();
-
- dungeon.set_link("Entrance", Direction::East, "Hallway").unwrap();
- dungeon.set_link("Hallway", Direction::West, "Magic Lab").unwrap();
-
- assert_eq!(dungeon.get_next_room("Entrance", Direction::East).unwrap().unwrap().name, "Hallway");
- assert_eq!(dungeon.get_next_room("Hallway", Direction::West).unwrap().unwrap().name, "Magic Lab");
- }
-
- const TEST_INPUT_6: &str = "";
-
- #[test]
- fn test_basic_6() {
- // .trim() за да премахнем първия и последния ред:
- let dd = Dungeon::from_reader(TEST_INPUT_6.trim().as_bytes());
- let k = dd.err().unwrap();
- println!("{:?}", k);
- }
-
- const TEST_INPUT_7: &str = "
-### Rooms
-- Entrance
-- Hallway
-
-## Links
-- Entrance -> East -> Hallway
-- Entrance -> West -> Hallway
- ";
-
-
- #[test]
- fn test_basic_7() {
- // .trim() за да премахнем първия и последния ред:
- let dd = Dungeon::from_reader(TEST_INPUT_7.trim().as_bytes());
- let k = dd.err().unwrap();
- println!("{:?}", k);
- }
-
-
- const TEST_INPUT_8: &str = "
-## Rooms
-- Entrance
-- Hallway
-
-## Links
-- Entrance -> East -> Hallway
-- Entrance ->-> West -> Hallway
- ";
-
-
- #[test]
- fn test_basic_8() {
- // .trim() за да премахнем първия и последния ред:
- let dd = Dungeon::from_reader(TEST_INPUT_8.trim().as_bytes());
- let k = dd.err().unwrap();
- println!("{:?}", k);
- }
-
- const TEST_INPUT_9: &str = "
-## Rooms
-- R1
-- R2
-- R3
-- R4
-
-## Links
-- R1 -> East -> R2
-- R2 -> West -> R3
-- R3 -> East -> R4
- ";
-
- #[test]
- fn test_basic_9() {
- // .trim() за да премахнем първия и последния ред:
- let dungeon = Dungeon::from_reader(TEST_INPUT_9.trim().as_bytes()).unwrap();
-
- let path = dungeon.find_path("R1", "R4").unwrap().unwrap();
- assert!(path.len() > 0);
- assert_eq!(path.first().unwrap().name, dungeon.get_room("R1").unwrap().name);
- assert_eq!(path.last().unwrap().name, dungeon.get_room("R4").unwrap().name);
- println!("{:?}", path);
- }
-
-
-
- const TEST_INPUT_10: &str = "
-## Rooms
-- Entrance
-- Hallway
-
-## Links
-- Entrance -> East -> Hallway
-- Entrance -> West -> R4
- ";
-
-
- #[test]
- fn test_basic_10() {
- // .trim() за да премахнем първия и последния ред:
- let dd = Dungeon::from_reader(TEST_INPUT_10.trim().as_bytes());
- let k = dd.err().unwrap();
- println!("{:?}", k);
- }
-
- const TEST_INPUT_11: &str = "
-## Rooms
-- Entrance
-- Hallway
-
-## Links
-- Entrance -> East -> Hallway
-- Entrance -> Weest -> Hallway
- ";
-
- #[test]
- fn test_basic_11() {
- // .trim() за да премахнем първия и последния ред:
- let dd = Dungeon::from_reader(TEST_INPUT_11.trim().as_bytes());
- let k = dd.err().unwrap();
- println!("{:?}", k);
}
}