diff --git a/README.md b/README.md index 9e57854..4804932 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ We encourage you to share your progress and ask questions in the Discussions sec | Day #32 | [Climbing The Leaderboard](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-05/Day-32_Climbing-The-Leaderboard) | :white_check_mark: | | Day #33 | [WERTYU](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-05/Day-33_WERTYU) | :white_check_mark: | | Day #34 | [Primary Arithmetic](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-05/Day-34_Primary-Arithmetic) | :white_check_mark: | -| Day #35 | [Dog And Gopher](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-05/Day-35_Dog-And-Gopher) | :white_large_square: | +| Day #35 | [Dog And Gopher](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-05/Day-35_Dog-And-Gopher) | :white_check_mark: | | Day #36 | [LCD Display](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-06/Day-36_LCD-Display) | :white_large_square: | | Day #37 | [Breaking The Records](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-06/Day-37_Breaking-The-Records) | :white_large_square: | | Day #38 | [Electronics Shop](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-06/Day-38_Electronics-Shop) | :white_large_square: | diff --git a/Week-05/Day-35_Dog-And-Gopher/day35/Cargo.toml b/Week-05/Day-35_Dog-And-Gopher/day35/Cargo.toml new file mode 100644 index 0000000..063bb20 --- /dev/null +++ b/Week-05/Day-35_Dog-And-Gopher/day35/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day35" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/Week-05/Day-35_Dog-And-Gopher/day35/src/lib.rs b/Week-05/Day-35_Dog-And-Gopher/day35/src/lib.rs new file mode 100644 index 0000000..67ea6ae --- /dev/null +++ b/Week-05/Day-35_Dog-And-Gopher/day35/src/lib.rs @@ -0,0 +1,85 @@ +use std::fs; + +pub fn gopher_escape_plan(filename: &str) -> Vec { + let error_return = vec![String::from("BAD FILE!")]; + + let mut content: Vec; + let mut field = Field::new(0, (0f32, 0f32), (0f32, 0f32)); + let mut result = Vec::new(); + + if let Ok(tmp_content) = fs::read_to_string(filename) { + content = tmp_content + .split_whitespace() + .map(|x| x.to_owned()) + .collect(); + } else { + return error_return; + } + + while !content.is_empty() { + if let Ok(tmp) = content[0].parse::() { + field.n = tmp; + } else { + return error_return; + } + + field.gopher_pos = match (content.get(1), content.get(2)) { + (Some(x), Some(y)) => match (x.parse(), y.parse()) { + (Ok(gopher_x), Ok(gopher_y)) => (gopher_x, gopher_y), + _ => return error_return, + }, + _ => return error_return, + }; + field.dog_pos = match (content.get(3), content.get(4)) { + (Some(x), Some(y)) => match (x.parse(), y.parse()) { + (Ok(dog_x), Ok(dog_y)) => (dog_x, dog_y), + _ => return error_return, + }, + _ => return error_return, + }; + + let mut found = false; + for i in 0..field.n { + let (x, y) = match (content.get(5 + i * 2), content.get(6 + i * 2)) { + (Some(x), Some(y)) => match (x.parse::(), y.parse::()) { + (Ok(x), Ok(y)) => (x, y), + _ => return error_return, + }, + _ => return error_return, + }; + + if (field.gopher_pos.0 - x).abs() + (field.gopher_pos.1 - y).abs() + < ((field.dog_pos.0 - x).abs() + (field.dog_pos.1 - y).abs() / 2f32) + { + result.push(format!( + "The gopher can escape through the hole at ({:.6},{:.6}).", + x, y + )); + found = true; + } + } + + if !found { + result.push(String::from("The gopher cannot escape.")); + } + content = content.split_off(5 + field.n * 2); + } + + result +} + +struct Field { + n: usize, + gopher_pos: (f32, f32), + dog_pos: (f32, f32), +} + +impl Field { + fn new(n: usize, gopher_pos: (f32, f32), dog_pos: (f32, f32)) -> Field { + Field { + n, + gopher_pos, + dog_pos, + } + } +} diff --git a/Week-05/Day-35_Dog-And-Gopher/day35/src/main.rs b/Week-05/Day-35_Dog-And-Gopher/day35/src/main.rs new file mode 100644 index 0000000..83a6872 --- /dev/null +++ b/Week-05/Day-35_Dog-And-Gopher/day35/src/main.rs @@ -0,0 +1,16 @@ +use day35::gopher_escape_plan; +use std::io::{self, Write}; + +fn main() { + println!("Insert the path of the file that contains the data"); + print!("> "); + io::stdout().flush().expect("Failed to flush stdout"); + + let mut buffer = String::new(); + io::stdin() + .read_line(&mut buffer) + .expect("Failed to read line"); + + let result = gopher_escape_plan(buffer.trim()); + println!("Result: {:?}", result); +} diff --git a/Week-05/Day-35_Dog-And-Gopher/day35/tests/examples.rs b/Week-05/Day-35_Dog-And-Gopher/day35/tests/examples.rs new file mode 100644 index 0000000..753e664 --- /dev/null +++ b/Week-05/Day-35_Dog-And-Gopher/day35/tests/examples.rs @@ -0,0 +1,50 @@ +#[cfg(test)] +mod examples { + use day35::gopher_escape_plan; + + #[test] + fn example1() { + assert_eq!( + gopher_escape_plan("../../../assets/day-35_sample_1_valid.txt"), + vec![ + "The gopher cannot escape.", + "The gopher can escape through the hole at (2.500000,2.500000)." + ] + ) + } + + #[test] + fn example2() { + assert_eq!( + gopher_escape_plan("../../../assets/day-35_sample_2_valid.txt"), + vec![ + "The gopher cannot escape.", + "The gopher can escape through the hole at (2.500000,2.500000)." + ] + ) + } + + #[test] + fn example3() { + assert_eq!( + gopher_escape_plan("../../../assets/day-35_sample_3_invalid.txt"), + vec!["BAD FILE!"] + ) + } + + #[test] + fn example4() { + assert_eq!( + gopher_escape_plan("../../../assets/day-35_sample_4_invalid.txt"), + vec!["BAD FILE!"] + ) + } + + #[test] + fn example5() { + assert_eq!( + gopher_escape_plan("../../../assets/day-35_sample_5_invalid.txt"), + vec!["BAD FILE!"] + ) + } +}