Решение на Dungeons and Compilers от Георги Попов

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

Към профила на Георги Попов

Резултати

  • 16 точки от тестове
  • 0 бонус точки
  • 16 точки общо
  • 12 успешни тест(а)
  • 3 неуспешни тест(а)

Код

use std::collections::HashMap;
use std::io::prelude::*;
use std::ptr;
#[derive(Debug)]
pub enum Errors {
DuplicateRoom(String),
UnknownRoom(String),
IoError(std::io::Error),
LineParseError { line_number: usize },
DirectionParseError(String),
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Direction {
North,
South,
East,
West,
}
#[derive(Debug)]
pub struct Room {
pub name: String,
pub neighbors: HashMap<Direction, String>,
// pub north_neighbors: String,
// pub east_neighbors: String,
// pub west_neighbors: String,
// pub south_neighbors: String,
}
pub struct Dungeon {
// Каквито полета ви трябват
// pub rooms: HashMap<String, *const Room>,
// pub current_room: *const Room
pub rooms: HashMap<String, Room>,
pub current_room: *const Room,
}
impl Dungeon {
pub fn new() -> Self {
Dungeon {
rooms: HashMap::new(),
current_room: ptr::null(),
}
}
pub fn add_room(&mut self, name: &str) -> Result<(), Errors> {
if self.rooms.contains_key(name) {
Err(Errors::DuplicateRoom(String::from(name)))
} else {
self.rooms.insert(
name.to_string(),
Room {
name: name.to_string(),
neighbors: HashMap::new(),
},
);
Ok(())
}
}
pub fn get_room(&self, room_name: &str) -> Result<&Room, Errors> {
if let Some(room) = self.rooms.get(room_name) {
Ok(room)
} else {
Err(Errors::UnknownRoom(String::from(room_name)))
}
}
pub fn set_link(
&mut self,
room_name: &str,
direction: Direction,
other_room_name: &str,
) -> Result<(), Errors> {
let room_exist = self.rooms.contains_key(room_name);
let other_room_exist = self.rooms.contains_key(other_room_name);
if room_exist {
let room = self.rooms.get_mut(room_name).unwrap();
if other_room_exist {
room.neighbors
.insert(direction, other_room_name.to_string());
let other_room = self.rooms.get_mut(other_room_name).unwrap();
other_room
.neighbors
.insert(get_opposite_direction(direction), room_name.to_string());
Ok(())
} else {
Err(Errors::UnknownRoom(String::from(other_room_name)))
}
} else {
Err(Errors::UnknownRoom(String::from(room_name)))
}
}
pub fn get_next_room(
&self,
room_name: &str,
direction: Direction,
) -> Result<Option<&Room>, Errors> {
if let Some(room) = self.rooms.get(room_name) {
if let Some(next_room_name) = room.neighbors.get(&direction) {
if let Some(next_room) = self.rooms.get(next_room_name) {
Ok(Some(next_room))
} else {
Ok(None)
}
} else {
Ok(None)
}
} else {
Err(Errors::UnknownRoom(String::from(room_name)))
}
}
pub fn from_reader<B: BufRead>(reader: B) -> Result<Self, Errors> {
let mut dungeon = Dungeon::new();
let mut line_number = 1;
let mut making_lines = 1;
let mut making_rooms = true;
let mut has_anything = false;
for line in reader.lines() {
has_anything = true;
if let Ok(formated_line) = line {
// println!("{} {}", formated_line, line_number);
match making_rooms {
true => {
if line_number == 1 {
if formated_line != String::from("## Rooms") {
// println!("It is different {:?}", formated_line);
return Err(Errors::LineParseError {
line_number: line_number,
});
}
line_number += 1;
continue;
}
if formated_line == String::from("") {
making_rooms = false;
line_number += 1;
continue;
}
let strr = formated_line.as_str();
if strr.starts_with("-") {
if let Some(a) = strr.chars().nth(1) {
if a != ' ' {
return Err(Errors::LineParseError {
line_number: line_number,
});
}
}
let (_, room_name) = strr.split_at(2);
let _ = dungeon.add_room(room_name)?;
// println!("SUCCESSS BEPCHE");
} else {
return Err(Errors::LineParseError {
line_number: line_number,
});
}
}
false => {
if making_lines == 1 {
if formated_line != String::from("## Links") {
// println!("It is different {:?}", formated_line);
return Err(Errors::LineParseError {
line_number: line_number,
});
}
making_lines += 1;
line_number += 1;
continue;
}
// println!("POCHVAME DA STROIM");
// println!("{:?}", formated_line);
let strr = formated_line.as_str();
if strr.starts_with("-") {
let (_, room_dir_room) = strr.split_at(2);
let v = room_dir_room.replace("-> ", "");
let vec: Vec<&str> = v.as_str().split(' ').collect();
let direction: Direction;
match vec[1] {
"North" => {
direction = Direction::North;
}
"South" => {
direction = Direction::South;
}
"West" => {
direction = Direction::West;
}
"East" => {
direction = Direction::East;
}
&_ => {
return Err(Errors::DirectionParseError(String::from(vec[1])))
}
}
// println!("Ei tva poluchihme bratko {}, {}", vec[0], vec[2]);
let _ = dungeon.set_link(vec[0], direction, vec[2])?;
// println!("SUCCESSS BEPCHE");
} else {
return Err(Errors::LineParseError {
line_number: line_number,
});
}
making_lines += 1;
}
}
}
line_number += 1;
}
if !has_anything {
return Err(Errors::LineParseError { line_number: 0 });
}
if making_rooms != false {
return Err(Errors::LineParseError {
line_number: line_number,
});
}
Ok(dungeon)
}
pub fn find_path(
&self,
start_room_name: &str,
end_room_name: &str,
) -> Result<Option<Vec<&Room>>, Errors> {
let mut parents: HashMap<&str, &str> = HashMap::new();
let mut q: Vec<&str> = Vec::new();
q.push(start_room_name);
while q.len() != 0 {
let mut room = q.remove(0);
if room == end_room_name {
//some logic for finding path here
let mut result: Vec<&Room> = Vec::new();
let final_room = self.get_room(end_room_name)?;
result.insert(0, final_room);
loop {
if let Some(parent_room_name) = parents.get(room) {
let actual_room = self.get_room(parent_room_name)?;
result.insert(0, actual_room);
room = parent_room_name;
if parent_room_name.to_string() == start_room_name.to_string() {
// println!("{:?}", result);
return Ok(Some(result));
}
}
}
}
let north = self.get_next_room(room, Direction::North)?;
match north {
Some(north_room) => {
q.push(north_room.name.as_str());
if !parents.contains_key(north_room.name.as_str()) {
parents.insert(north_room.name.as_str(), room);
}
}
None => {}
}
let south = self.get_next_room(room, Direction::South)?;
match south {
Some(south_room) => {
q.push(south_room.name.as_str());
if !parents.contains_key(south_room.name.as_str()) {
parents.insert(south_room.name.as_str(), room);
}
}
None => {}
}
let west = self.get_next_room(room, Direction::West)?;
match west {
Some(west_room) => {
q.push(west_room.name.as_str());
if !parents.contains_key(west_room.name.as_str()) {
parents.insert(west_room.name.as_str(), room);
}
}
None => {}
}
let east = self.get_next_room(room, Direction::East)?;
match east {
Some(east_room) => {
q.push(east_room.name.as_str());
if !parents.contains_key(east_room.name.as_str()) {
parents.insert(east_room.name.as_str(), room);
}
}
None => {}
}
}
Ok(None)
}
}
pub fn get_opposite_direction(direction: Direction) -> Direction {
match direction {
Direction::North => Direction::South,
Direction::East => Direction::West,
Direction::West => Direction::East,
Direction::South => Direction::North,
}
}

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

Compiling solution v0.1.0 (/tmp/d20220116-3533338-14b3lk0/solution)
    Finished test [unoptimized + debuginfo] target(s) in 3.72s
     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 ... FAILED
test solution_test::test_invalid_parsing ... ok
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 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Timeout', tests/solution_test.rs:354:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- 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_io_error stdout ----
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Timeout', tests/solution_test.rs:194:5


failures:
    solution_test::test_finding_a_reflexive_path
    solution_test::test_finding_no_path
    solution_test::test_io_error

test result: FAILED. 12 passed; 3 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.01s

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

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

Георги качи първо решение на 09.01.2022 11:16 (преди почти 4 години)

Георги качи решение на 11.01.2022 00:33 (преди над 3 години)

-use std::any::type_name;
use std::collections::HashMap;
-use std::io;
use std::io::prelude::*;
use std::ptr;
#[derive(Debug)]
pub enum Errors {
DuplicateRoom(String),
UnknownRoom(String),
IoError(std::io::Error),
LineParseError { line_number: usize },
DirectionParseError(String),
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Direction {
North,
South,
East,
West,
}
#[derive(Debug)]
pub struct Room {
pub name: String,
pub neighbors: HashMap<Direction, String>,
// pub north_neighbors: String,
// pub east_neighbors: String,
// pub west_neighbors: String,
// pub south_neighbors: String,
}
pub struct Dungeon {
// Каквито полета ви трябват
// pub rooms: HashMap<String, *const Room>,
// pub current_room: *const Room
pub rooms: HashMap<String, Room>,
pub current_room: *const Room,
}
impl Dungeon {
pub fn new() -> Self {
Dungeon {
rooms: HashMap::new(),
current_room: ptr::null(),
}
}
pub fn add_room(&mut self, name: &str) -> Result<(), Errors> {
if self.rooms.contains_key(name) {
Err(Errors::DuplicateRoom(String::from("Ima veche takava")))
} else {
self.rooms.insert(
name.to_string(),
Room {
name: name.to_string(),
neighbors: HashMap::new(),
},
);
Ok(())
}
}
pub fn get_room(&self, room_name: &str) -> Result<&Room, Errors> {
if let Some(room) = self.rooms.get(room_name) {
Ok(room)
} else {
Err(Errors::UnknownRoom(String::from(
"Ne znam da imame takava staq bratlee",
)))
}
}
pub fn set_link(
&mut self,
room_name: &str,
direction: Direction,
other_room_name: &str,
) -> Result<(), Errors> {
let room_exist = self.rooms.contains_key(room_name);
let other_room_exist = self.rooms.contains_key(other_room_name);
if room_exist {
let room = self.rooms.get_mut(room_name).unwrap();
if other_room_exist {
room.neighbors
.insert(direction, other_room_name.to_string());
let other_room = self.rooms.get_mut(other_room_name).unwrap();
other_room
.neighbors
.insert(get_opposite_direction(direction), room_name.to_string());
Ok(())
} else {
Err(Errors::UnknownRoom(String::from(
"Kak syzdavash vryzka kym neshto deto go nqma",
)))
}
} else {
Err(Errors::UnknownRoom(String::from(
"Kak syzdavash vryzka ot neshto deto go nqma",
)))
}
}
pub fn get_next_room(
&self,
room_name: &str,
direction: Direction,
) -> Result<Option<&Room>, Errors> {
if let Some(room) = self.rooms.get(room_name) {
if let Some(next_room_name) = room.neighbors.get(&direction) {
if let Some(next_room) = self.rooms.get(next_room_name) {
Ok(Some(next_room))
} else {
Ok(None)
}
} else {
Ok(None)
}
} else {
Err(Errors::UnknownRoom(String::from(
"Kak da stane kato razi staq q nqma",
)))
}
}
pub fn from_reader<B: BufRead>(reader: B) -> Result<Self, Errors> {
let mut dungeon = Dungeon::new();
let mut line_number = 1;
let mut making_lines = 1;
let mut making_rooms = true;
for line in reader.lines() {
if let Ok(formated_line) = line {
// println!("{} {}", formated_line, line_number);
match making_rooms {
true => {
if line_number == 1 {
if formated_line != String::from("## Rooms") {
// println!("It is different {:?}", formated_line);
return Err(Errors::LineParseError {
line_number: line_number,
});
}
line_number += 1;
continue;
}
if formated_line == String::from("") {
making_rooms = false;
line_number += 1;
continue;
}
let strr = formated_line.as_str();
if strr.starts_with("-") {
let (_, room_name) = strr.split_at(2);
let _ = dungeon.add_room(room_name)?;
// println!("SUCCESSS BEPCHE");
} else {
return Err(Errors::LineParseError {
line_number: line_number,
});
}
}
false => {
if making_lines == 1 {
if formated_line != String::from("## Links") {
// println!("It is different {:?}", formated_line);
return Err(Errors::LineParseError {
line_number: line_number,
});
}
making_lines += 1;
line_number += 1;
continue;
}
// println!("POCHVAME DA STROIM");
// println!("{:?}", formated_line);
let strr = formated_line.as_str();
if strr.starts_with("-") {
let (_, room_dir_room) = strr.split_at(2);
let v = room_dir_room.replace("-> ", "");
let vec: Vec<&str> = v.as_str().split(' ').collect();
let direction: Direction;
match vec[1] {
"North" => {
direction = Direction::North;
}
"South" => {
direction = Direction::South;
}
"West" => {
direction = Direction::West;
}
"East" => {
direction = Direction::East;
}
&_ => {
return Err(Errors::DirectionParseError(String::from(
"Kva e taz posoka eeee",
)))
}
}
// println!("Ei tva poluchihme bratko {}, {}", vec[0], vec[2]);
let _ = dungeon.set_link(vec[0], direction, vec[2])?;
// println!("SUCCESSS BEPCHE");
} else {
return Err(Errors::LineParseError {
line_number: line_number,
});
}
making_lines += 1;
}
}
}
line_number += 1;
}
Ok(dungeon)
}
pub fn find_path(
&self,
start_room_name: &str,
end_room_name: &str,
) -> Result<Option<Vec<&Room>>, Errors> {
let mut parents: HashMap<&str, &str> = HashMap::new();
let mut q: Vec<&str> = Vec::new();
q.push(start_room_name);
while q.len() != 0 {
let mut room = q.remove(0);
if room == end_room_name {
//some logic for finding path here
let mut result: Vec<&Room> = Vec::new();
let final_room = self.get_room(end_room_name)?;
result.insert(0, final_room);
loop {
if let Some(parent_room_name) = parents.get(room) {
let actual_room = self.get_room(parent_room_name)?;
result.insert(0, actual_room);
room = parent_room_name;
if parent_room_name.to_string() == start_room_name.to_string() {
// println!("{:?}", result);
return Ok(Some(result));
}
}
}
}
let north = self.get_next_room(room, Direction::North)?;
match north {
Some(north_room) => {
q.push(north_room.name.as_str());
if !parents.contains_key(north_room.name.as_str()) {
parents.insert(north_room.name.as_str(), room);
}
}
None => {}
}
let south = self.get_next_room(room, Direction::South)?;
match south {
Some(south_room) => {
q.push(south_room.name.as_str());
if !parents.contains_key(south_room.name.as_str()) {
parents.insert(south_room.name.as_str(), room);
}
}
None => {}
}
let west = self.get_next_room(room, Direction::West)?;
match west {
Some(west_room) => {
q.push(west_room.name.as_str());
if !parents.contains_key(west_room.name.as_str()) {
parents.insert(west_room.name.as_str(), room);
}
}
None => {}
}
let east = self.get_next_room(room, Direction::East)?;
match east {
Some(east_room) => {
q.push(east_room.name.as_str());
if !parents.contains_key(east_room.name.as_str()) {
parents.insert(east_room.name.as_str(), room);
}
}
None => {}
}
}
Ok(None)
}
}
pub fn get_opposite_direction(direction: Direction) -> Direction {
match direction {
Direction::North => Direction::South,
Direction::East => Direction::West,
Direction::West => Direction::East,
Direction::South => Direction::North,
}
}

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

use std::collections::HashMap;
use std::io::prelude::*;
use std::ptr;
#[derive(Debug)]
pub enum Errors {
DuplicateRoom(String),
UnknownRoom(String),
IoError(std::io::Error),
LineParseError { line_number: usize },
DirectionParseError(String),
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Direction {
North,
South,
East,
West,
}
#[derive(Debug)]
pub struct Room {
pub name: String,
pub neighbors: HashMap<Direction, String>,
// pub north_neighbors: String,
// pub east_neighbors: String,
// pub west_neighbors: String,
// pub south_neighbors: String,
}
pub struct Dungeon {
// Каквито полета ви трябват
// pub rooms: HashMap<String, *const Room>,
// pub current_room: *const Room
pub rooms: HashMap<String, Room>,
pub current_room: *const Room,
}
impl Dungeon {
pub fn new() -> Self {
Dungeon {
rooms: HashMap::new(),
current_room: ptr::null(),
}
}
pub fn add_room(&mut self, name: &str) -> Result<(), Errors> {
if self.rooms.contains_key(name) {
- Err(Errors::DuplicateRoom(String::from("Ima veche takava")))
+ Err(Errors::DuplicateRoom(String::from(name)))
} else {
self.rooms.insert(
name.to_string(),
Room {
name: name.to_string(),
neighbors: HashMap::new(),
},
);
Ok(())
}
}
pub fn get_room(&self, room_name: &str) -> Result<&Room, Errors> {
if let Some(room) = self.rooms.get(room_name) {
Ok(room)
} else {
- Err(Errors::UnknownRoom(String::from(
- "Ne znam da imame takava staq bratlee",
- )))
+ Err(Errors::UnknownRoom(String::from(room_name)))
}
}
pub fn set_link(
&mut self,
room_name: &str,
direction: Direction,
other_room_name: &str,
) -> Result<(), Errors> {
let room_exist = self.rooms.contains_key(room_name);
let other_room_exist = self.rooms.contains_key(other_room_name);
if room_exist {
let room = self.rooms.get_mut(room_name).unwrap();
if other_room_exist {
room.neighbors
.insert(direction, other_room_name.to_string());
let other_room = self.rooms.get_mut(other_room_name).unwrap();
other_room
.neighbors
.insert(get_opposite_direction(direction), room_name.to_string());
Ok(())
} else {
- Err(Errors::UnknownRoom(String::from(
- "Kak syzdavash vryzka kym neshto deto go nqma",
- )))
+ Err(Errors::UnknownRoom(String::from(other_room_name)))
}
} else {
- Err(Errors::UnknownRoom(String::from(
- "Kak syzdavash vryzka ot neshto deto go nqma",
- )))
+ Err(Errors::UnknownRoom(String::from(room_name)))
}
}
pub fn get_next_room(
&self,
room_name: &str,
direction: Direction,
) -> Result<Option<&Room>, Errors> {
if let Some(room) = self.rooms.get(room_name) {
if let Some(next_room_name) = room.neighbors.get(&direction) {
if let Some(next_room) = self.rooms.get(next_room_name) {
Ok(Some(next_room))
} else {
Ok(None)
}
} else {
Ok(None)
}
} else {
- Err(Errors::UnknownRoom(String::from(
- "Kak da stane kato razi staq q nqma",
- )))
+ Err(Errors::UnknownRoom(String::from(room_name)))
}
}
pub fn from_reader<B: BufRead>(reader: B) -> Result<Self, Errors> {
let mut dungeon = Dungeon::new();
let mut line_number = 1;
let mut making_lines = 1;
let mut making_rooms = true;
for line in reader.lines() {
if let Ok(formated_line) = line {
// println!("{} {}", formated_line, line_number);
match making_rooms {
true => {
if line_number == 1 {
if formated_line != String::from("## Rooms") {
// println!("It is different {:?}", formated_line);
return Err(Errors::LineParseError {
line_number: line_number,
});
}
line_number += 1;
continue;
}
if formated_line == String::from("") {
making_rooms = false;
line_number += 1;
continue;
}
let strr = formated_line.as_str();
if strr.starts_with("-") {
let (_, room_name) = strr.split_at(2);
let _ = dungeon.add_room(room_name)?;
// println!("SUCCESSS BEPCHE");
} else {
return Err(Errors::LineParseError {
line_number: line_number,
});
}
}
false => {
if making_lines == 1 {
if formated_line != String::from("## Links") {
// println!("It is different {:?}", formated_line);
return Err(Errors::LineParseError {
line_number: line_number,
});
}
making_lines += 1;
line_number += 1;
continue;
}
// println!("POCHVAME DA STROIM");
// println!("{:?}", formated_line);
let strr = formated_line.as_str();
if strr.starts_with("-") {
let (_, room_dir_room) = strr.split_at(2);
let v = room_dir_room.replace("-> ", "");
let vec: Vec<&str> = v.as_str().split(' ').collect();
let direction: Direction;
match vec[1] {
"North" => {
direction = Direction::North;
}
"South" => {
direction = Direction::South;
}
"West" => {
direction = Direction::West;
}
"East" => {
direction = Direction::East;
}
&_ => {
- return Err(Errors::DirectionParseError(String::from(
- "Kva e taz posoka eeee",
- )))
+ return Err(Errors::DirectionParseError(String::from(vec[1])))
}
}
// println!("Ei tva poluchihme bratko {}, {}", vec[0], vec[2]);
let _ = dungeon.set_link(vec[0], direction, vec[2])?;
// println!("SUCCESSS BEPCHE");
} else {
return Err(Errors::LineParseError {
line_number: line_number,
});
}
making_lines += 1;
}
}
}
line_number += 1;
}
Ok(dungeon)
}
pub fn find_path(
&self,
start_room_name: &str,
end_room_name: &str,
) -> Result<Option<Vec<&Room>>, Errors> {
let mut parents: HashMap<&str, &str> = HashMap::new();
let mut q: Vec<&str> = Vec::new();
q.push(start_room_name);
while q.len() != 0 {
let mut room = q.remove(0);
if room == end_room_name {
//some logic for finding path here
let mut result: Vec<&Room> = Vec::new();
let final_room = self.get_room(end_room_name)?;
result.insert(0, final_room);
loop {
if let Some(parent_room_name) = parents.get(room) {
let actual_room = self.get_room(parent_room_name)?;
result.insert(0, actual_room);
room = parent_room_name;
if parent_room_name.to_string() == start_room_name.to_string() {
// println!("{:?}", result);
return Ok(Some(result));
}
}
}
}
let north = self.get_next_room(room, Direction::North)?;
match north {
Some(north_room) => {
q.push(north_room.name.as_str());
if !parents.contains_key(north_room.name.as_str()) {
parents.insert(north_room.name.as_str(), room);
}
}
None => {}
}
let south = self.get_next_room(room, Direction::South)?;
match south {
Some(south_room) => {
q.push(south_room.name.as_str());
if !parents.contains_key(south_room.name.as_str()) {
parents.insert(south_room.name.as_str(), room);
}
}
None => {}
}
let west = self.get_next_room(room, Direction::West)?;
match west {
Some(west_room) => {
q.push(west_room.name.as_str());
if !parents.contains_key(west_room.name.as_str()) {
parents.insert(west_room.name.as_str(), room);
}
}
None => {}
}
let east = self.get_next_room(room, Direction::East)?;
match east {
Some(east_room) => {
q.push(east_room.name.as_str());
if !parents.contains_key(east_room.name.as_str()) {
parents.insert(east_room.name.as_str(), room);
}
}
None => {}
}
}
Ok(None)
}
}
pub fn get_opposite_direction(direction: Direction) -> Direction {
match direction {
Direction::North => Direction::South,
Direction::East => Direction::West,
Direction::West => Direction::East,
Direction::South => Direction::North,
}
}

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

use std::collections::HashMap;
use std::io::prelude::*;
use std::ptr;
#[derive(Debug)]
pub enum Errors {
DuplicateRoom(String),
UnknownRoom(String),
IoError(std::io::Error),
LineParseError { line_number: usize },
DirectionParseError(String),
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Direction {
North,
South,
East,
West,
}
#[derive(Debug)]
pub struct Room {
pub name: String,
pub neighbors: HashMap<Direction, String>,
// pub north_neighbors: String,
// pub east_neighbors: String,
// pub west_neighbors: String,
// pub south_neighbors: String,
}
pub struct Dungeon {
// Каквито полета ви трябват
// pub rooms: HashMap<String, *const Room>,
// pub current_room: *const Room
pub rooms: HashMap<String, Room>,
pub current_room: *const Room,
}
impl Dungeon {
pub fn new() -> Self {
Dungeon {
rooms: HashMap::new(),
current_room: ptr::null(),
}
}
pub fn add_room(&mut self, name: &str) -> Result<(), Errors> {
if self.rooms.contains_key(name) {
Err(Errors::DuplicateRoom(String::from(name)))
} else {
self.rooms.insert(
name.to_string(),
Room {
name: name.to_string(),
neighbors: HashMap::new(),
},
);
Ok(())
}
}
pub fn get_room(&self, room_name: &str) -> Result<&Room, Errors> {
if let Some(room) = self.rooms.get(room_name) {
Ok(room)
} else {
Err(Errors::UnknownRoom(String::from(room_name)))
}
}
pub fn set_link(
&mut self,
room_name: &str,
direction: Direction,
other_room_name: &str,
) -> Result<(), Errors> {
let room_exist = self.rooms.contains_key(room_name);
let other_room_exist = self.rooms.contains_key(other_room_name);
if room_exist {
let room = self.rooms.get_mut(room_name).unwrap();
if other_room_exist {
room.neighbors
.insert(direction, other_room_name.to_string());
let other_room = self.rooms.get_mut(other_room_name).unwrap();
other_room
.neighbors
.insert(get_opposite_direction(direction), room_name.to_string());
Ok(())
} else {
Err(Errors::UnknownRoom(String::from(other_room_name)))
}
} else {
Err(Errors::UnknownRoom(String::from(room_name)))
}
}
pub fn get_next_room(
&self,
room_name: &str,
direction: Direction,
) -> Result<Option<&Room>, Errors> {
if let Some(room) = self.rooms.get(room_name) {
if let Some(next_room_name) = room.neighbors.get(&direction) {
if let Some(next_room) = self.rooms.get(next_room_name) {
Ok(Some(next_room))
} else {
Ok(None)
}
} else {
Ok(None)
}
} else {
Err(Errors::UnknownRoom(String::from(room_name)))
}
}
pub fn from_reader<B: BufRead>(reader: B) -> Result<Self, Errors> {
let mut dungeon = Dungeon::new();
let mut line_number = 1;
let mut making_lines = 1;
let mut making_rooms = true;
for line in reader.lines() {
if let Ok(formated_line) = line {
// println!("{} {}", formated_line, line_number);
match making_rooms {
true => {
if line_number == 1 {
if formated_line != String::from("## Rooms") {
// println!("It is different {:?}", formated_line);
return Err(Errors::LineParseError {
line_number: line_number,
});
}
line_number += 1;
continue;
}
if formated_line == String::from("") {
making_rooms = false;
line_number += 1;
continue;
}
let strr = formated_line.as_str();
if strr.starts_with("-") {
+ if let Some(a) = strr.chars().nth(1) {
+ if a != ' ' {
+ return Err(Errors::LineParseError {
+ line_number: line_number,
+ });
+ }
+ }
let (_, room_name) = strr.split_at(2);
let _ = dungeon.add_room(room_name)?;
// println!("SUCCESSS BEPCHE");
} else {
return Err(Errors::LineParseError {
line_number: line_number,
});
}
}
false => {
if making_lines == 1 {
if formated_line != String::from("## Links") {
// println!("It is different {:?}", formated_line);
return Err(Errors::LineParseError {
line_number: line_number,
});
}
making_lines += 1;
line_number += 1;
continue;
}
// println!("POCHVAME DA STROIM");
// println!("{:?}", formated_line);
let strr = formated_line.as_str();
if strr.starts_with("-") {
let (_, room_dir_room) = strr.split_at(2);
let v = room_dir_room.replace("-> ", "");
let vec: Vec<&str> = v.as_str().split(' ').collect();
let direction: Direction;
match vec[1] {
"North" => {
direction = Direction::North;
}
"South" => {
direction = Direction::South;
}
"West" => {
direction = Direction::West;
}
"East" => {
direction = Direction::East;
}
&_ => {
return Err(Errors::DirectionParseError(String::from(vec[1])))
}
}
// println!("Ei tva poluchihme bratko {}, {}", vec[0], vec[2]);
let _ = dungeon.set_link(vec[0], direction, vec[2])?;
// println!("SUCCESSS BEPCHE");
} else {
return Err(Errors::LineParseError {
line_number: line_number,
});
}
making_lines += 1;
}
}
}
line_number += 1;
}
Ok(dungeon)
}
pub fn find_path(
&self,
start_room_name: &str,
end_room_name: &str,
) -> Result<Option<Vec<&Room>>, Errors> {
let mut parents: HashMap<&str, &str> = HashMap::new();
let mut q: Vec<&str> = Vec::new();
q.push(start_room_name);
while q.len() != 0 {
let mut room = q.remove(0);
if room == end_room_name {
//some logic for finding path here
let mut result: Vec<&Room> = Vec::new();
let final_room = self.get_room(end_room_name)?;
result.insert(0, final_room);
loop {
if let Some(parent_room_name) = parents.get(room) {
let actual_room = self.get_room(parent_room_name)?;
result.insert(0, actual_room);
room = parent_room_name;
if parent_room_name.to_string() == start_room_name.to_string() {
// println!("{:?}", result);
return Ok(Some(result));
}
}
}
}
let north = self.get_next_room(room, Direction::North)?;
match north {
Some(north_room) => {
q.push(north_room.name.as_str());
if !parents.contains_key(north_room.name.as_str()) {
parents.insert(north_room.name.as_str(), room);
}
}
None => {}
}
let south = self.get_next_room(room, Direction::South)?;
match south {
Some(south_room) => {
q.push(south_room.name.as_str());
if !parents.contains_key(south_room.name.as_str()) {
parents.insert(south_room.name.as_str(), room);
}
}
None => {}
}
let west = self.get_next_room(room, Direction::West)?;
match west {
Some(west_room) => {
q.push(west_room.name.as_str());
if !parents.contains_key(west_room.name.as_str()) {
parents.insert(west_room.name.as_str(), room);
}
}
None => {}
}
let east = self.get_next_room(room, Direction::East)?;
match east {
Some(east_room) => {
q.push(east_room.name.as_str());
if !parents.contains_key(east_room.name.as_str()) {
parents.insert(east_room.name.as_str(), room);
}
}
None => {}
}
}
Ok(None)
}
}
pub fn get_opposite_direction(direction: Direction) -> Direction {
match direction {
Direction::North => Direction::South,
Direction::East => Direction::West,
Direction::West => Direction::East,
Direction::South => Direction::North,
}
}

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

use std::collections::HashMap;
use std::io::prelude::*;
use std::ptr;
#[derive(Debug)]
pub enum Errors {
DuplicateRoom(String),
UnknownRoom(String),
IoError(std::io::Error),
LineParseError { line_number: usize },
DirectionParseError(String),
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Direction {
North,
South,
East,
West,
}
#[derive(Debug)]
pub struct Room {
pub name: String,
pub neighbors: HashMap<Direction, String>,
// pub north_neighbors: String,
// pub east_neighbors: String,
// pub west_neighbors: String,
// pub south_neighbors: String,
}
pub struct Dungeon {
// Каквито полета ви трябват
// pub rooms: HashMap<String, *const Room>,
// pub current_room: *const Room
pub rooms: HashMap<String, Room>,
pub current_room: *const Room,
}
impl Dungeon {
pub fn new() -> Self {
Dungeon {
rooms: HashMap::new(),
current_room: ptr::null(),
}
}
pub fn add_room(&mut self, name: &str) -> Result<(), Errors> {
if self.rooms.contains_key(name) {
Err(Errors::DuplicateRoom(String::from(name)))
} else {
self.rooms.insert(
name.to_string(),
Room {
name: name.to_string(),
neighbors: HashMap::new(),
},
);
Ok(())
}
}
pub fn get_room(&self, room_name: &str) -> Result<&Room, Errors> {
if let Some(room) = self.rooms.get(room_name) {
Ok(room)
} else {
Err(Errors::UnknownRoom(String::from(room_name)))
}
}
pub fn set_link(
&mut self,
room_name: &str,
direction: Direction,
other_room_name: &str,
) -> Result<(), Errors> {
let room_exist = self.rooms.contains_key(room_name);
let other_room_exist = self.rooms.contains_key(other_room_name);
if room_exist {
let room = self.rooms.get_mut(room_name).unwrap();
if other_room_exist {
room.neighbors
.insert(direction, other_room_name.to_string());
let other_room = self.rooms.get_mut(other_room_name).unwrap();
other_room
.neighbors
.insert(get_opposite_direction(direction), room_name.to_string());
Ok(())
} else {
Err(Errors::UnknownRoom(String::from(other_room_name)))
}
} else {
Err(Errors::UnknownRoom(String::from(room_name)))
}
}
pub fn get_next_room(
&self,
room_name: &str,
direction: Direction,
) -> Result<Option<&Room>, Errors> {
if let Some(room) = self.rooms.get(room_name) {
if let Some(next_room_name) = room.neighbors.get(&direction) {
if let Some(next_room) = self.rooms.get(next_room_name) {
Ok(Some(next_room))
} else {
Ok(None)
}
} else {
Ok(None)
}
} else {
Err(Errors::UnknownRoom(String::from(room_name)))
}
}
pub fn from_reader<B: BufRead>(reader: B) -> Result<Self, Errors> {
let mut dungeon = Dungeon::new();
let mut line_number = 1;
let mut making_lines = 1;
let mut making_rooms = true;
+ let mut has_anything = false;
for line in reader.lines() {
+ has_anything = true;
if let Ok(formated_line) = line {
// println!("{} {}", formated_line, line_number);
match making_rooms {
true => {
if line_number == 1 {
if formated_line != String::from("## Rooms") {
// println!("It is different {:?}", formated_line);
return Err(Errors::LineParseError {
line_number: line_number,
});
}
line_number += 1;
continue;
}
if formated_line == String::from("") {
making_rooms = false;
line_number += 1;
continue;
}
let strr = formated_line.as_str();
if strr.starts_with("-") {
if let Some(a) = strr.chars().nth(1) {
if a != ' ' {
return Err(Errors::LineParseError {
line_number: line_number,
});
}
}
let (_, room_name) = strr.split_at(2);
let _ = dungeon.add_room(room_name)?;
// println!("SUCCESSS BEPCHE");
} else {
return Err(Errors::LineParseError {
line_number: line_number,
});
}
}
false => {
if making_lines == 1 {
if formated_line != String::from("## Links") {
// println!("It is different {:?}", formated_line);
return Err(Errors::LineParseError {
line_number: line_number,
});
}
making_lines += 1;
line_number += 1;
continue;
}
// println!("POCHVAME DA STROIM");
// println!("{:?}", formated_line);
let strr = formated_line.as_str();
if strr.starts_with("-") {
let (_, room_dir_room) = strr.split_at(2);
let v = room_dir_room.replace("-> ", "");
let vec: Vec<&str> = v.as_str().split(' ').collect();
let direction: Direction;
match vec[1] {
"North" => {
direction = Direction::North;
}
"South" => {
direction = Direction::South;
}
"West" => {
direction = Direction::West;
}
"East" => {
direction = Direction::East;
}
&_ => {
return Err(Errors::DirectionParseError(String::from(vec[1])))
}
}
// println!("Ei tva poluchihme bratko {}, {}", vec[0], vec[2]);
let _ = dungeon.set_link(vec[0], direction, vec[2])?;
// println!("SUCCESSS BEPCHE");
} else {
return Err(Errors::LineParseError {
line_number: line_number,
});
}
making_lines += 1;
}
}
}
line_number += 1;
}
-
+ if !has_anything {
+ return Err(Errors::LineParseError { line_number: 0 });
+ }
+ if making_rooms != false {
+ return Err(Errors::LineParseError {
+ line_number: line_number,
+ });
+ }
Ok(dungeon)
}
pub fn find_path(
&self,
start_room_name: &str,
end_room_name: &str,
) -> Result<Option<Vec<&Room>>, Errors> {
let mut parents: HashMap<&str, &str> = HashMap::new();
let mut q: Vec<&str> = Vec::new();
q.push(start_room_name);
while q.len() != 0 {
let mut room = q.remove(0);
if room == end_room_name {
//some logic for finding path here
let mut result: Vec<&Room> = Vec::new();
let final_room = self.get_room(end_room_name)?;
result.insert(0, final_room);
loop {
if let Some(parent_room_name) = parents.get(room) {
let actual_room = self.get_room(parent_room_name)?;
result.insert(0, actual_room);
room = parent_room_name;
if parent_room_name.to_string() == start_room_name.to_string() {
// println!("{:?}", result);
return Ok(Some(result));
}
}
}
}
let north = self.get_next_room(room, Direction::North)?;
match north {
Some(north_room) => {
q.push(north_room.name.as_str());
if !parents.contains_key(north_room.name.as_str()) {
parents.insert(north_room.name.as_str(), room);
}
}
None => {}
}
let south = self.get_next_room(room, Direction::South)?;
match south {
Some(south_room) => {
q.push(south_room.name.as_str());
if !parents.contains_key(south_room.name.as_str()) {
parents.insert(south_room.name.as_str(), room);
}
}
None => {}
}
let west = self.get_next_room(room, Direction::West)?;
match west {
Some(west_room) => {
q.push(west_room.name.as_str());
if !parents.contains_key(west_room.name.as_str()) {
parents.insert(west_room.name.as_str(), room);
}
}
None => {}
}
let east = self.get_next_room(room, Direction::East)?;
match east {
Some(east_room) => {
q.push(east_room.name.as_str());
if !parents.contains_key(east_room.name.as_str()) {
parents.insert(east_room.name.as_str(), room);
}
}
None => {}
}
}
Ok(None)
}
}
pub fn get_opposite_direction(direction: Direction) -> Direction {
match direction {
Direction::North => Direction::South,
Direction::East => Direction::West,
Direction::West => Direction::East,
Direction::South => Direction::North,
}
}