Решение на Dungeons and Compilers от Георги Бойчев

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

Към профила на Георги Бойчев

Резултати

  • 8 точки от тестове
  • 0 бонус точки
  • 8 точки общо
  • 6 успешни тест(а)
  • 9 неуспешни тест(а)

Код

use std::{fmt::Error, io::BufRead};
/// Различните грешки, които ще очакваме да върнете като резултат от някои невалидни операции.
/// Повече детайли по-долу.
///
#[derive(Debug)]
pub enum Errors {
DuplicateRoom(String),
UnknownRoom(String),
IoError(std::io::Error),
LineParseError { line_number: usize },
DirectionParseError(String),
}
/// Четирите посоки, в които може една стая да има съседи. Може да добавите още trait
/// имплементации, за да си улесните живота.
///
#[derive(Clone, Copy)]
pub enum Direction {
North,
South,
East,
West,
}
/// Една стая в подземията. Дефинира се само с име, макар че в по-интересна имплементация може да
/// държи item-и, противници...
///
pub struct Room {
pub name: String,
pub connections: Vec<(Direction, String)>
}
/// Контейнер за стаите и не само. Ще работим предимно със тази структура.
///
pub struct Dungeon {
pub rooms: Vec<Room>
}
impl Dungeon {
/// Конструиране на празен Dungeon, в който няма никакви стаи.
///
pub fn new() -> Self {
Dungeon {
rooms: Vec::new()
}
}
/// Добавяне на стая към Dungeon с име `name`. Връща `Ok(())` при успех. Ако вече има стая с
/// такова име, очакваме да върнете `Errors::DuplicateRoom` с името.
///
pub fn add_room(&mut self, new_name: &str) -> Result<(), Errors> {
for i in &self.rooms {
if i.name.eq(new_name) {
return Err(Errors::DuplicateRoom("There already exists a room with the same name".to_string()));
}
}
let new_room = Room {
connections: vec![(Direction::North, "".to_string()), (Direction::East, "".to_string()),
(Direction::South, "".to_string()), (Direction::West, "".to_string())],
name: new_name.to_string(),
};
self.rooms.push(new_room);
Ok(())
}
/// Прочитане на дадена стая -- когато извикаме `get_room`, очакваме reference към `Room`
/// структурата с това име.
///
/// Ако няма такава стая, очакваме `Errors::UnknownRoom` с подаденото име.
///
pub fn get_room(&self, room_name: &str) -> Result<&Room, Errors> {
for i in &self.rooms {
if i.name.eq(room_name) {
return Ok(&i);
}
}
return Err(Errors::UnknownRoom("No such room".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> {
let mut found_room_1 = false;
let mut found_room_2 = false;
let mut room_1_num = 0;
let mut room_2_num = 0;
let mut counter = 0;
for i in &self.rooms {
if i.name.eq(room_name) {
found_room_1 = true;
room_1_num = counter;
}
if i.name.eq(other_room_name) {
found_room_2 = true;
room_2_num = counter;
}
counter += 1;
}
if found_room_1 == false || found_room_2 == false {
return Err(Errors::UnknownRoom("Could not find one or two of the rooms".to_string()));
}
let direction_num;
match direction{
Direction::East => direction_num = 1,
Direction::West => direction_num = 3,
Direction::North => direction_num = 0,
Direction::South => direction_num = 2,
}
let op_direction_num;
match direction{
Direction::East => op_direction_num = 3,
Direction::West => op_direction_num = 1,
Direction::North => op_direction_num = 2,
Direction::South => op_direction_num = 0,
}
self.rooms.get_mut(room_1_num).unwrap().connections.get_mut(direction_num).unwrap().1 = other_room_name.to_string();
self.rooms.get_mut(room_2_num).unwrap().connections.get_mut(op_direction_num).unwrap().1 = room_name.to_string();
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> {
let mut room_exists = false;
let mut direction_exists = false;
for i in &self.rooms {
if i.name.eq(room_name) {
room_exists = true;
for d in &i.connections {
if std::mem::discriminant(&d.0) == std::mem::discriminant(&direction) {
if !d.1.eq("") {
let next_room_name = d.1.to_owned();
for r in &self.rooms {
if r.name.eq(&next_room_name) {
let result: Option<&Room> = Some(&r);
return Ok(result);
}
}
}
}
}
}
}
if room_exists && !direction_exists {
return Ok(None)
} else {
return Err(Errors::UnknownRoom("The room does not exist".to_string()));
}
}
}
impl Dungeon {
/// Прочитаме структурата на dungeon от нещо, което имплементира `BufRead`. Това може да е
/// файл, или, ако тестваме, може да е просто колекция от байтове.
///
/// Успешен резултат връща новосъздадения dungeon, пакетиран в `Ok`.
///
/// Вижте по-долу за обяснение на грешките, които очакваме.
///
pub fn from_reader<B: BufRead>(reader: B) -> Result<Self, Errors> {
todo!()
}
}
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> {
todo!()
}
}
/// match_prefix("- ", "- Foo") //=> Some("Foo")
/// match_prefix("- ", "Bar") //=> None
///
fn match_prefix<'a, 'b>(prefix: &'a str, input: &'b str) -> Option<&'b str> {
todo!()
}

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

Compiling solution v0.1.0 (/tmp/d20220116-3533338-u4t6zz/solution)
warning: unused import: `fmt::Error`
 --> src/lib.rs:1:11
  |
1 | use std::{fmt::Error, io::BufRead};
  |           ^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: unused variable: `prefix`
   --> src/lib.rs:203:25
    |
203 | fn match_prefix<'a, 'b>(prefix: &'a str, input: &'b str) -> Option<&'b str> {
    |                         ^^^^^^ help: if this is intentional, prefix it with an underscore: `_prefix`
    |
    = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `input`
   --> src/lib.rs:203:42
    |
203 | fn match_prefix<'a, 'b>(prefix: &'a str, input: &'b str) -> Option<&'b str> {
    |                                          ^^^^^ help: if this is intentional, prefix it with an underscore: `_input`

warning: unused variable: `reader`
   --> src/lib.rs:180:36
    |
180 |     pub fn from_reader<B: BufRead>(reader: B) -> Result<Self, Errors> {
    |                                    ^^^^^^ help: if this is intentional, prefix it with an underscore: `_reader`

warning: unused variable: `start_room_name`
   --> src/lib.rs:194:9
    |
194 |         start_room_name: &str,
    |         ^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_start_room_name`

warning: unused variable: `end_room_name`
   --> src/lib.rs:195:9
    |
195 |         end_room_name: &str
    |         ^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_end_room_name`

warning: variable does not need to be mutable
   --> src/lib.rs:145:13
    |
145 |         let mut direction_exists = false;
    |             ----^^^^^^^^^^^^^^^^
    |             |
    |             help: remove this `mut`
    |
    = note: `#[warn(unused_mut)]` on by default

warning: function is never used: `match_prefix`
   --> src/lib.rs:203:4
    |
203 | fn match_prefix<'a, 'b>(prefix: &'a str, input: &'b str) -> Option<&'b str> {
    |    ^^^^^^^^^^^^
    |
    = note: `#[warn(dead_code)]` on by default

warning: `solution` (lib) generated 8 warnings
    Finished test [unoptimized + debuginfo] target(s) in 3.14s
     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 ... FAILED
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 ... FAILED
test solution_test::test_parsing_no_rooms_or_links ... FAILED
test solution_test::test_parsing_rooms ... FAILED
test solution_test::test_room_errors ... ok
test solution_test::test_room_links ... ok

failures:

---- solution_test::test_finding_a_direct_path stdout ----
thread '<unnamed>' panicked at 'not yet implemented', src/lib.rs:197: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:306:5

---- solution_test::test_finding_a_reflexive_path stdout ----
thread '<unnamed>' panicked at 'not yet implemented', src/lib.rs:197:9
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 '<unnamed>' panicked at 'not yet implemented', src/lib.rs:197:9
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:320:5

---- solution_test::test_finding_no_path stdout ----
thread '<unnamed>' panicked at 'not yet implemented', src/lib.rs:197: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 'not yet implemented', /tmp/d20220116-3533338-u4t6zz/solution/src/lib.rs:181:9

---- solution_test::test_io_error stdout ----
thread '<unnamed>' panicked at 'not yet implemented', /tmp/d20220116-3533338-u4t6zz/solution/src/lib.rs:181:9
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:194:5

---- solution_test::test_parsing_cyrillic_rooms stdout ----
thread 'main' panicked at 'not yet implemented', /tmp/d20220116-3533338-u4t6zz/solution/src/lib.rs:181:9

---- solution_test::test_parsing_no_rooms_or_links stdout ----
thread 'main' panicked at 'not yet implemented', /tmp/d20220116-3533338-u4t6zz/solution/src/lib.rs:181:9

---- solution_test::test_parsing_rooms stdout ----
thread 'main' panicked at 'not yet implemented', /tmp/d20220116-3533338-u4t6zz/solution/src/lib.rs:181:9


failures:
    solution_test::test_finding_a_direct_path
    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
    solution_test::test_parsing_cyrillic_rooms
    solution_test::test_parsing_no_rooms_or_links
    solution_test::test_parsing_rooms

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

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

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

Георги качи първо решение на 11.01.2022 16:29 (преди над 3 години)