Решение на Dungeons and Compilers от Мерилин Писина

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

Към профила на Мерилин Писина

Резултати

  • 13 точки от тестове
  • 0 бонус точки
  • 13 точки общо
  • 10 успешни тест(а)
  • 5 неуспешни тест(а)

Код

use std::io::BufRead;
use std::collections::HashMap;
use std::collections::VecDeque;
fn match_prefix<'a, 'b>(prefix: &'a str, input: &'b str) -> Option<&'b str> {
input.strip_prefix(prefix)
}
#[derive(Debug)]
pub enum Errors {
DuplicateRoom(String),
UnknownRoom(String),
IoError(std::io::Error),
LineParseError { line_number: usize },
DirectionParseError(String),
}
#[derive(Clone, Copy)]
pub enum Direction {
North,
South,
East,
West,
}
#[derive(Debug)]
pub struct Room {
pub name: String,
pub north: String,
pub south: String,
pub east: String,
pub west: String,
}
pub struct Dungeon {
rooms: HashMap<String, Room>
}
impl<'a> Dungeon {
pub fn new() -> Self {
Dungeon { rooms: HashMap::new() }
}
pub fn add_room(&mut self, name: &'a 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(),
east: String::from(""),
west: String::from(""),
north: String::from(""),
south: String::from(""),
}
);
Ok(())
}
}
pub fn get_room(&self, room_name: &str) -> Result<&Room, Errors> {
match self.rooms.get(room_name) {
Some(room) => Ok(room),
None => Err(Errors::UnknownRoom(room_name.to_string()))
}
}
pub fn set_link(
&mut self,
room_name: &str,
direction: Direction,
other_room_name: &str,
) -> Result<(), Errors> {
match (self.rooms.get(room_name), self.rooms.get(other_room_name)) {
(Some(_), Some(_)) => {
match direction {
Direction::North => {
let room_opt = self.rooms.get_mut(room_name);
if let Some(room) = room_opt {
room.north = String::from(other_room_name);
}
let room_opt = self.rooms.get_mut(other_room_name);
if let Some(room) = room_opt {
room.south = String::from(room_name);
}
},
Direction::South => {
let room_opt = self.rooms.get_mut(room_name);
if let Some(room) = room_opt {
room.south = String::from(other_room_name);
}
let room_opt = self.rooms.get_mut(other_room_name);
if let Some(room) = room_opt {
room.north = String::from(room_name);
}
},
Direction::East => {
let room_opt = self.rooms.get_mut(room_name);
if let Some(room) = room_opt {
room.east = String::from(other_room_name);
}
let room_opt = self.rooms.get_mut(other_room_name);
if let Some(room) = room_opt {
room.west = String::from(room_name);
}
},
Direction::West => {
let room_opt = self.rooms.get_mut(room_name);
if let Some(room) = room_opt {
room.west = String::from(other_room_name);
}
let room_opt = self.rooms.get_mut(other_room_name);
if let Some(room) = room_opt {
room.east = String::from(room_name);
}
},
}
Ok(())
}
(Some(_), None) => Err(Errors::UnknownRoom(other_room_name.to_string())),
(None, _) => Err(Errors::UnknownRoom(room_name.to_string())),
}
}
pub fn get_next_room(
&self,
room_name: &str,
direction: Direction
) -> Result<Option<&Room>, Errors> {
match self.rooms.get(room_name) {
None => return Err(Errors::UnknownRoom(room_name.to_string())),
Some(room) => {
match direction {
Direction::North => {
let north_name = room.north.clone();
match north_name.len() {
0 => return Ok(None),
_ => return Ok(self.rooms.get(&north_name)),
}
},
Direction::South => {
let south_name = room.south.clone();
match south_name.len() {
0 => return Ok(None),
_ => return Ok(self.rooms.get(&south_name)),
}
},
Direction::East => {
let east_name = room.east.clone();
match east_name.len() {
0 => return Ok(None),
_ => return Ok(self.rooms.get(&east_name)),
}
},
Direction::West => {
let west_name = room.west.clone();
match west_name.len() {
0 => return Ok(None),
_ => return Ok(self.rooms.get(&west_name)),
}
},
}
}
}
}
pub fn from_reader<B: BufRead>(mut reader: B) -> Result<Self, Errors> {
let mut dungeon = Dungeon { rooms: HashMap::new() };
let mut index = 0;
let mut entrances_started = false;
let mut entrances_checked = false;
for line in reader.lines() {
let line_content = match line {
Ok(text) if text.len() == 0 => {
if !entrances_started && index != 0 {
entrances_started = true;
index = index + 1;
continue;
}
return Err(Errors::LineParseError { line_number: index });
},
Ok(text) => text,
Err(_) => return Err(Errors::LineParseError { line_number: index }),
};
if index == 0 {
let err = match match_prefix("## ", &line_content) {
Some(s) if !s.eq("Rooms") => return Err(Errors::LineParseError { line_number: index }),
Some(s) => s,
None => return Err(Errors::LineParseError { line_number: index }),
};
}
else if entrances_started && !entrances_checked {
entrances_checked = true;
let err = match match_prefix("## ", &line_content) {
Some(s) if !s.eq("Links") => return Err(Errors::LineParseError { line_number: index }),
Some(s) => s,
None => return Err(Errors::LineParseError { line_number: index }),
};
}
else if !entrances_started {
let parsed = match_prefix("- ", &line_content);
match parsed {
Some(room_name) => {
if let Err(e) = dungeon.add_room(room_name) {
return Err(e);
}
},
None => return Err(Errors::LineParseError { line_number: index }),
}
}
else {
let parsed = match_prefix("- ", &line_content);
match parsed {
Some(room_name) => {
let split = room_name.split(" -> ").collect::<Vec<&str>>();
if split.len() != 3 {
return Err(Errors::LineParseError { line_number: index });
}
let direction = match split[1] {
"North" => Direction::North,
"South" => Direction::South,
"East" => Direction::East,
"West" => Direction::West,
_ => return Err(Errors::LineParseError { line_number: index }),
};
if let Err(e) = dungeon.set_link(split[0], direction, split[2]) {
return Err(e);
}
},
None => return Err(Errors::LineParseError { line_number: index }),
}
}
index = index + 1;
}
if index == 0 {
return Err(Errors::LineParseError { line_number: 0 });
}
return Ok(dungeon);
}
pub fn find_path(
&self,
start_room_name: &str,
end_room_name: &str
) -> Result<Option<Vec<&Room>>, Errors> {
let room_get = self.get_room(start_room_name);
let room = match room_get {
Err(e) => return Err(e),
Ok(r) => r,
};
let mut queue = VecDeque::<&Room>::new();
let mut visited: Vec<String> = Vec::new();
queue.push_back(room);
let mut path = HashMap::<String, String>::new();
while !queue.is_empty() {
let front = queue.pop_front().unwrap();
if visited.contains(&front.name.clone()) {
continue;
}
visited.push(front.name.clone());
if front.name == end_room_name {
break;
}
if front.north != "" {
let next_room = match self.get_room(&front.north) {
Err(e) => return Err(e),
Ok(r) => r,
};
path.insert(next_room.name.clone(), front.name.clone());
queue.push_back(next_room);
}
if front.south != "" {
let next_room = match self.get_room(&front.south) {
Err(e) => return Err(e),
Ok(r) => r,
};
path.insert(next_room.name.clone(), front.name.clone());
queue.push_back(next_room);
}
if front.east != "" {
let next_room = match self.get_room(&front.east) {
Err(e) => return Err(e),
Ok(r) => r,
};
path.insert(next_room.name.clone(), front.name.clone());
queue.push_back(next_room);
}
if front.west != "" {
let next_room = match self.get_room(&front.west) {
Err(e) => return Err(e),
Ok(r) => r,
};
path.insert(next_room.name.clone(), front.name.clone());
queue.push_back(next_room);
}
}
if let None = path.get(end_room_name) {
return Ok(None);
}
let mut path_constructed: Vec<&Room> = Vec::new();
let mut current_room: String = end_room_name.to_string();
let next_room = match self.get_room(&current_room) {
Err(e) => return Err(e),
Ok(r) => r,
};
path_constructed.push(next_room);
while true {
match path.get(&current_room) {
Some(r) if r == start_room_name => {
let next_room = match self.get_room(&start_room_name) {
Err(e) => return Err(e),
Ok(r) => r,
};
path_constructed.push(next_room);
path_constructed.reverse();
return Ok(Some(path_constructed));
},
Some(r) => {
let next_room = match self.get_room(&r) {
Err(e) => return Err(e),
Ok(r) => r,
};
current_room = r.clone();
path_constructed.push(next_room);
},
None => return Ok(None),
}
}
return Ok(None);
}
}

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

Compiling solution v0.1.0 (/tmp/d20220116-3533338-emzdwn/solution)
warning: denote infinite loops with `loop { ... }`
   --> src/lib.rs:329:9
    |
329 |         while true {
    |         ^^^^^^^^^^ help: use `loop`
    |
    = note: `#[warn(while_true)]` on by default

warning: unused variable: `err`
   --> src/lib.rs:193:21
    |
193 |                 let err = match match_prefix("## ", &line_content) {
    |                     ^^^ help: if this is intentional, prefix it with an underscore: `_err`
    |
    = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `err`
   --> src/lib.rs:202:21
    |
202 |                 let err = match match_prefix("## ", &line_content) {
    |                     ^^^ help: if this is intentional, prefix it with an underscore: `_err`

warning: variable does not need to be mutable
   --> src/lib.rs:173:36
    |
173 |     pub fn from_reader<B: BufRead>(mut reader: B) -> Result<Self, Errors> {
    |                                    ----^^^^^^
    |                                    |
    |                                    help: remove this `mut`
    |
    = note: `#[warn(unused_mut)]` on by default

warning: `solution` (lib) generated 4 warnings
    Finished test [unoptimized + debuginfo] target(s) in 3.70s
     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 ... FAILED
test solution_test::test_finding_no_path ... FAILED
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 ... 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_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_finding_an_indirect_path stdout ----
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Timeout', tests/solution_test.rs:320:5

---- solution_test::test_finding_no_path stdout ----
thread '<unnamed>' panicked at 'assertion failed: path.is_err()', tests/solution_test.rs:382:9
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:372:5

---- solution_test::test_invalid_parsing stdout ----
thread 'main' panicked at 'assertion failed: matches!(Dungeon :: from_reader(TEST_INPUT_4.trim().as_bytes()),\n         Err(Errors :: LineParseError { line_number : 1 }))', tests/solution_test.rs:277:5

---- solution_test::test_io_error stdout ----
thread '<unnamed>' panicked at 'assertion failed: matches!(dungeon, Err(Errors :: IoError(_)))', tests/solution_test.rs:196:9
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:194:5


failures:
    solution_test::test_finding_a_reflexive_path
    solution_test::test_finding_an_indirect_path
    solution_test::test_finding_no_path
    solution_test::test_invalid_parsing
    solution_test::test_io_error

test result: FAILED. 10 passed; 5 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.02s

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

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

Мерилин качи първо решение на 11.01.2022 15:59 (преди над 3 години)

Мерилин качи решение на 11.01.2022 16:08 (преди над 3 години)

- use std::io::BufRead;
- use std::collections::HashMap;
- use std::collections::VecDeque;
+use std::io::BufRead;
+use std::collections::HashMap;
+use std::collections::VecDeque;
- fn match_prefix<'a, 'b>(prefix: &'a str, input: &'b str) -> Option<&'b str> {
- input.strip_prefix(prefix)
+fn match_prefix<'a, 'b>(prefix: &'a str, input: &'b str) -> Option<&'b str> {
+ input.strip_prefix(prefix)
+}
+
+#[derive(Debug)]
+pub enum Errors {
+ DuplicateRoom(String),
+ UnknownRoom(String),
+ IoError(std::io::Error),
+ LineParseError { line_number: usize },
+ DirectionParseError(String),
+}
+
+#[derive(Clone, Copy)]
+pub enum Direction {
+ North,
+ South,
+ East,
+ West,
+}
+
+#[derive(Debug)]
+pub struct Room {
+ pub name: String,
+ pub north: String,
+ pub south: String,
+ pub east: String,
+ pub west: String,
+}
+
+pub struct Dungeon {
+ rooms: HashMap<String, Room>
+}
+
+impl<'a> Dungeon {
+ pub fn new() -> Self {
+ Dungeon { rooms: HashMap::new() }
}
- #[derive(Debug)]
- pub enum Errors {
- DuplicateRoom(String),
- UnknownRoom(String),
- IoError(std::io::Error),
- LineParseError { line_number: usize },
- DirectionParseError(String),
+ pub fn add_room(&mut self, name: &'a 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(),
+ east: String::from(""),
+ west: String::from(""),
+ north: String::from(""),
+ south: String::from(""),
+ }
+ );
+ Ok(())
+ }
}
-
- #[derive(Clone, Copy)]
- pub enum Direction {
- North,
- South,
- East,
- West,
- }
-
- pub struct Room {
- pub name: String,
- pub north: String,
- pub south: String,
- pub east: String,
- pub west: String,
- }
-
- pub struct Dungeon {
- rooms: HashMap<String, Room>
- }
-
- impl<'a> Dungeon {
- pub fn new() -> Self {
- Dungeon { rooms: HashMap::new() }
+
+ pub fn get_room(&self, room_name: &str) -> Result<&Room, Errors> {
+ match self.rooms.get(room_name) {
+ Some(room) => Ok(room),
+ None => Err(Errors::UnknownRoom(room_name.to_string()))
}
-
- pub fn add_room(&mut self, name: &'a 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(),
- east: String::from(""),
- west: String::from(""),
- north: String::from(""),
- south: String::from(""),
- }
- );
+ }
+
+ pub fn set_link(
+ &mut self,
+ room_name: &str,
+ direction: Direction,
+ other_room_name: &str,
+ ) -> Result<(), Errors> {
+ match (self.rooms.get(room_name), self.rooms.get(other_room_name)) {
+ (Some(_), Some(_)) => {
+ match direction {
+ Direction::North => {
+ let room_opt = self.rooms.get_mut(room_name);
+ if let Some(room) = room_opt {
+ room.north = String::from(other_room_name);
+ }
+
+ let room_opt = self.rooms.get_mut(other_room_name);
+ if let Some(room) = room_opt {
+ room.south = String::from(room_name);
+ }
+ },
+ Direction::South => {
+ let room_opt = self.rooms.get_mut(room_name);
+ if let Some(room) = room_opt {
+ room.south = String::from(other_room_name);
+ }
+
+ let room_opt = self.rooms.get_mut(other_room_name);
+ if let Some(room) = room_opt {
+ room.north = String::from(room_name);
+ }
+ },
+ Direction::East => {
+ let room_opt = self.rooms.get_mut(room_name);
+ if let Some(room) = room_opt {
+ room.east = String::from(other_room_name);
+ }
+
+ let room_opt = self.rooms.get_mut(other_room_name);
+ if let Some(room) = room_opt {
+ room.west = String::from(room_name);
+ }
+ },
+ Direction::West => {
+ let room_opt = self.rooms.get_mut(room_name);
+ if let Some(room) = room_opt {
+ room.west = String::from(other_room_name);
+ }
+
+ let room_opt = self.rooms.get_mut(other_room_name);
+ if let Some(room) = room_opt {
+ room.east = String::from(room_name);
+ }
+ },
+ }
Ok(())
}
+ (Some(_), None) => Err(Errors::UnknownRoom(other_room_name.to_string())),
+ (None, _) => Err(Errors::UnknownRoom(room_name.to_string())),
}
-
- pub fn get_room(&self, room_name: &str) -> Result<&Room, Errors> {
- match self.rooms.get(room_name) {
- Some(room) => Ok(room),
- None => Err(Errors::UnknownRoom(room_name.to_string()))
- }
- }
-
- pub fn set_link(
- &mut self,
- room_name: &str,
- direction: Direction,
- other_room_name: &str,
- ) -> Result<(), Errors> {
- match (self.rooms.get(room_name), self.rooms.get(other_room_name)) {
- (Some(_), Some(_)) => {
- match direction {
- Direction::North => {
- let room_opt = self.rooms.get_mut(room_name);
- if let Some(room) = room_opt {
- room.north = String::from(other_room_name);
- }
-
- let room_opt = self.rooms.get_mut(other_room_name);
- if let Some(room) = room_opt {
- room.south = String::from(room_name);
- }
- },
- Direction::South => {
- let room_opt = self.rooms.get_mut(room_name);
- if let Some(room) = room_opt {
- room.south = String::from(other_room_name);
- }
-
- let room_opt = self.rooms.get_mut(other_room_name);
- if let Some(room) = room_opt {
- room.north = String::from(room_name);
- }
- },
- Direction::East => {
- let room_opt = self.rooms.get_mut(room_name);
- if let Some(room) = room_opt {
- room.east = String::from(other_room_name);
- }
-
- let room_opt = self.rooms.get_mut(other_room_name);
- if let Some(room) = room_opt {
- room.west = String::from(room_name);
- }
- },
- Direction::West => {
- let room_opt = self.rooms.get_mut(room_name);
- if let Some(room) = room_opt {
- room.west = String::from(other_room_name);
- }
-
- let room_opt = self.rooms.get_mut(other_room_name);
- if let Some(room) = room_opt {
- room.east = String::from(room_name);
- }
- },
- }
- Ok(())
+ }
+
+ pub fn get_next_room(
+ &self,
+ room_name: &str,
+ direction: Direction
+ ) -> Result<Option<&Room>, Errors> {
+ match self.rooms.get(room_name) {
+ None => return Err(Errors::UnknownRoom(room_name.to_string())),
+ Some(room) => {
+ match direction {
+ Direction::North => {
+ let north_name = room.north.clone();
+ match north_name.len() {
+ 0 => return Ok(None),
+ _ => return Ok(self.rooms.get(&north_name)),
+ }
+ },
+ Direction::South => {
+ let south_name = room.south.clone();
+ match south_name.len() {
+ 0 => return Ok(None),
+ _ => return Ok(self.rooms.get(&south_name)),
+ }
+ },
+ Direction::East => {
+ let east_name = room.east.clone();
+ match east_name.len() {
+ 0 => return Ok(None),
+ _ => return Ok(self.rooms.get(&east_name)),
+ }
+ },
+ Direction::West => {
+ let west_name = room.west.clone();
+ match west_name.len() {
+ 0 => return Ok(None),
+ _ => return Ok(self.rooms.get(&west_name)),
+ }
+ },
}
- (Some(_), None) => Err(Errors::UnknownRoom(other_room_name.to_string())),
- (None, _) => Err(Errors::UnknownRoom(room_name.to_string())),
}
}
-
- pub fn get_next_room(
- &self,
- room_name: &str,
- direction: Direction
- ) -> Result<Option<&Room>, Errors> {
- match self.rooms.get(room_name) {
- None => return Err(Errors::UnknownRoom(room_name.to_string())),
- Some(room) => {
- match direction {
- Direction::North => {
- let north_name = room.north.clone();
- match north_name.len() {
- 0 => return Ok(None),
- _ => return Ok(self.rooms.get(&north_name)),
- }
- },
- Direction::South => {
- let south_name = room.south.clone();
- match south_name.len() {
- 0 => return Ok(None),
- _ => return Ok(self.rooms.get(&south_name)),
- }
- },
- Direction::East => {
- let east_name = room.east.clone();
- match east_name.len() {
- 0 => return Ok(None),
- _ => return Ok(self.rooms.get(&east_name)),
- }
- },
- Direction::West => {
- let west_name = room.west.clone();
- match west_name.len() {
- 0 => return Ok(None),
- _ => return Ok(self.rooms.get(&west_name)),
- }
- },
+ }
+
+ pub fn from_reader<B: BufRead>(mut reader: B) -> Result<Self, Errors> {
+ let mut dungeon = Dungeon { rooms: HashMap::new() };
+ let mut index = 0;
+ let mut entrances_started = false;
+ let mut entrances_checked = false;
+ for line in reader.lines() {
+ let line_content = match line {
+ Ok(text) if text.len() == 0 => {
+ if !entrances_started && index != 0 {
+ entrances_started = true;
+ index = index + 1;
+ continue;
}
- }
+ return Err(Errors::LineParseError { line_number: index });
+ },
+ Ok(text) => text,
+ Err(_) => return Err(Errors::LineParseError { line_number: index }),
+ };
+
+ if index == 0 {
+ let err = match match_prefix("## ", &line_content) {
+ Some(s) if !s.eq("Rooms") => return Err(Errors::LineParseError { line_number: index }),
+ Some(s) => s,
+ None => return Err(Errors::LineParseError { line_number: index }),
+ };
}
- }
-
- pub fn from_reader<B: BufRead>(mut reader: B) -> Result<Self, Errors> {
- let mut dungeon = Dungeon { rooms: HashMap::new() };
- let mut index = 0;
- let mut entrances_started = false;
- let mut entrances_checked = false;
- for line in reader.lines() {
- let line_content = match line {
- Ok(text) if text.len() == 0 => {
- if !entrances_started && index != 0 {
- entrances_started = true;
- index = index + 1;
- continue;
+
+ else if entrances_started && !entrances_checked {
+ entrances_checked = true;
+ let err = match match_prefix("## ", &line_content) {
+ Some(s) if !s.eq("Links") => return Err(Errors::LineParseError { line_number: index }),
+ Some(s) => s,
+ None => return Err(Errors::LineParseError { line_number: index }),
+ };
+ }
+
+ else if !entrances_started {
+ let parsed = match_prefix("- ", &line_content);
+ match parsed {
+ Some(room_name) => {
+ if let Err(e) = dungeon.add_room(room_name) {
+ return Err(e);
}
- return Err(Errors::LineParseError { line_number: index });
},
- Ok(text) => text,
- Err(_) => return Err(Errors::LineParseError { line_number: index }),
- };
-
- if index == 0 {
- let err = match match_prefix("## ", &line_content) {
- Some(s) if !s.eq("Rooms") => return Err(Errors::LineParseError { line_number: index }),
- Some(s) => s,
- None => return Err(Errors::LineParseError { line_number: index }),
- };
+ None => return Err(Errors::LineParseError { line_number: index }),
}
+ }
- else if entrances_started && !entrances_checked {
- entrances_checked = true;
- let err = match match_prefix("## ", &line_content) {
- Some(s) if !s.eq("Links") => return Err(Errors::LineParseError { line_number: index }),
- Some(s) => s,
- None => return Err(Errors::LineParseError { line_number: index }),
- };
+ else {
+ let parsed = match_prefix("- ", &line_content);
+ match parsed {
+ Some(room_name) => {
+ let split = room_name.split(" -> ").collect::<Vec<&str>>();
+ if split.len() != 3 {
+ return Err(Errors::LineParseError { line_number: index });
+ }
+ let direction = match split[1] {
+ "North" => Direction::North,
+ "South" => Direction::South,
+ "East" => Direction::East,
+ "West" => Direction::West,
+ _ => return Err(Errors::LineParseError { line_number: index }),
+ };
+ if let Err(e) = dungeon.set_link(split[0], direction, split[2]) {
+ return Err(e);
+ }
+ },
+ None => return Err(Errors::LineParseError { line_number: index }),
}
+ }
- else if !entrances_started {
- let parsed = match_prefix("- ", &line_content);
- match parsed {
- Some(room_name) => {
- if let Err(e) = dungeon.add_room(room_name) {
- return Err(e);
- }
- },
- None => return Err(Errors::LineParseError { line_number: index }),
- }
- }
+ index = index + 1;
+ }
+ if index == 0 {
+ return Err(Errors::LineParseError { line_number: 0 });
+ }
- else {
- let parsed = match_prefix("- ", &line_content);
- match parsed {
- Some(room_name) => {
- let split = room_name.split(" -> ").collect::<Vec<&str>>();
- if split.len() != 3 {
- return Err(Errors::LineParseError { line_number: index });
- }
- let direction = match split[1] {
- "North" => Direction::North,
- "South" => Direction::South,
- "East" => Direction::East,
- "West" => Direction::West,
- _ => return Err(Errors::LineParseError { line_number: index }),
- };
- if let Err(e) = dungeon.set_link(split[0], direction, split[2]) {
- return Err(e);
- }
- },
- None => return Err(Errors::LineParseError { line_number: index }),
- }
- }
+ return Ok(dungeon);
+ }
- index = index + 1;
+ pub fn find_path(
+ &self,
+ start_room_name: &str,
+ end_room_name: &str
+ ) -> Result<Option<Vec<&Room>>, Errors> {
+ let room_get = self.get_room(start_room_name);
+ let room = match room_get {
+ Err(e) => return Err(e),
+ Ok(r) => r,
+ };
+
+ let mut queue = VecDeque::<&Room>::new();
+ let mut visited: Vec<String> = Vec::new();
+ queue.push_back(room);
+ let mut path = HashMap::<String, String>::new();
+
+ while !queue.is_empty() {
+ let front = queue.pop_front().unwrap();
+
+ if visited.contains(&front.name.clone()) {
+ continue;
}
- if index == 0 {
- return Err(Errors::LineParseError { line_number: 0 });
+
+ visited.push(front.name.clone());
+ if front.name == end_room_name {
+ break;
}
- return Ok(dungeon);
- }
-
- pub fn find_path(
- &self,
- start_room_name: &str,
- end_room_name: &str
- ) -> Result<Option<Vec<&Room>>, Errors> {
- let room_get = self.get_room(start_room_name);
- let room = match room_get {
- Err(e) => return Err(e),
- Ok(r) => r,
- };
+ if front.north != "" {
+ let next_room = match self.get_room(&front.north) {
+ Err(e) => return Err(e),
+ Ok(r) => r,
+ };
+ path.insert(next_room.name.clone(), front.name.clone());
+ queue.push_back(next_room);
+ }
- let mut queue = VecDeque::<&Room>::new();
- let mut visited: Vec<String> = Vec::new();
- queue.push_back(room);
- let mut path = HashMap::<String, String>::new();
-
- while !queue.is_empty() {
- let front = queue.pop_front().unwrap();
+ if front.south != "" {
+ let next_room = match self.get_room(&front.south) {
+ Err(e) => return Err(e),
+ Ok(r) => r,
+ };
+ path.insert(next_room.name.clone(), front.name.clone());
+ queue.push_back(next_room);
+ }
- if visited.contains(&front.name.clone()) {
- continue;
- }
+ if front.east != "" {
+ let next_room = match self.get_room(&front.east) {
+ Err(e) => return Err(e),
+ Ok(r) => r,
+ };
+ path.insert(next_room.name.clone(), front.name.clone());
+ queue.push_back(next_room);
+ }
- visited.push(front.name.clone());
- if front.name == end_room_name {
- break;
- }
+ if front.west != "" {
+ let next_room = match self.get_room(&front.west) {
+ Err(e) => return Err(e),
+ Ok(r) => r,
+ };
+ path.insert(next_room.name.clone(), front.name.clone());
+ queue.push_back(next_room);
+ }
+ }
- if front.north != "" {
- let next_room = match self.get_room(&front.north) {
+ if let None = path.get(end_room_name) {
+ return Ok(None);
+ }
+
+ let mut path_constructed: Vec<&Room> = Vec::new();
+ let mut current_room: String = end_room_name.to_string();
+ let next_room = match self.get_room(&current_room) {
+ Err(e) => return Err(e),
+ Ok(r) => r,
+ };
+ path_constructed.push(next_room);
+ while true {
+ match path.get(&current_room) {
+ Some(r) if r == start_room_name => {
+ let next_room = match self.get_room(&start_room_name) {
Err(e) => return Err(e),
Ok(r) => r,
};
- path.insert(next_room.name.clone(), front.name.clone());
- queue.push_back(next_room);
- }
-
- if front.south != "" {
- let next_room = match self.get_room(&front.south) {
+ path_constructed.push(next_room);
+ path_constructed.reverse();
+ return Ok(Some(path_constructed));
+ },
+ Some(r) => {
+ let next_room = match self.get_room(&r) {
Err(e) => return Err(e),
Ok(r) => r,
};
- path.insert(next_room.name.clone(), front.name.clone());
- queue.push_back(next_room);
- }
-
- if front.east != "" {
- let next_room = match self.get_room(&front.east) {
- Err(e) => return Err(e),
- Ok(r) => r,
- };
- path.insert(next_room.name.clone(), front.name.clone());
- queue.push_back(next_room);
- }
-
- if front.west != "" {
- let next_room = match self.get_room(&front.west) {
- Err(e) => return Err(e),
- Ok(r) => r,
- };
- path.insert(next_room.name.clone(), front.name.clone());
- queue.push_back(next_room);
- }
+ current_room = r.clone();
+ path_constructed.push(next_room);
+ },
+ None => return Ok(None),
}
-
- if let None = path.get(end_room_name) {
- return Ok(None);
- }
-
- let mut path_constructed: Vec<&Room> = Vec::new();
- let mut current_room: String = end_room_name.to_string();
- let next_room = match self.get_room(&current_room) {
- Err(e) => return Err(e),
- Ok(r) => r,
- };
- path_constructed.push(next_room);
- while true {
- match path.get(&current_room) {
- Some(r) if r == start_room_name => {
- let next_room = match self.get_room(&start_room_name) {
- Err(e) => return Err(e),
- Ok(r) => r,
- };
- path_constructed.push(next_room);
- path_constructed.reverse();
- return Ok(Some(path_constructed));
- },
- Some(r) => {
- let next_room = match self.get_room(&r) {
- Err(e) => return Err(e),
- Ok(r) => r,
- };
- path_constructed.push(next_room);
- },
- None => return Ok(None),
- }
- }
- return Ok(None);
}
- }
+ return Ok(None);
+ }
+}