diff --git a/README.md b/README.md index e0f899b..20bc83d 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ We encourage you to share your progress and ask questions in the Discussions sec | Day #25 | [Coin Trouble](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-04/Day-25_Coin-Trouble) | :white_check_mark: | | Day #26 | [Briefcase Lock](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-04/Day-26_Briefcase-Lock) | :white_check_mark: | | Day #27 | [Task Scheduler](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-04/Day-27_Task-Scheduler) | :white_check_mark: | -| Day #28 | [Word Search](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-04/Day-28_Word-Search) | :white_large_square: | +| Day #28 | [Word Search](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-04/Day-28_Word-Search) | :white_check_mark: | | Day #29 | [Traffic Light Checker](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-05/Day-29_Traffic-Light-Checker) | :white_large_square: | | Day #30 | [The Maximum Value](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-05/Day-30_The-Maximum-Value) | :white_large_square: | | Day #31 | [The Time In Words](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-05/Day-31_The-Time-In-Words) | :white_large_square: | diff --git a/Week-04/Day-28_Word-Search/day28/Cargo.toml b/Week-04/Day-28_Word-Search/day28/Cargo.toml new file mode 100644 index 0000000..42fb58e --- /dev/null +++ b/Week-04/Day-28_Word-Search/day28/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day28" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/Week-04/Day-28_Word-Search/day28/src/lib.rs b/Week-04/Day-28_Word-Search/day28/src/lib.rs new file mode 100644 index 0000000..580209b --- /dev/null +++ b/Week-04/Day-28_Word-Search/day28/src/lib.rs @@ -0,0 +1,72 @@ +use std::{char, collections::HashMap}; + +pub fn word_search(board: &[Vec], words: &[&str]) -> Vec { + let mut first_char_to_word = HashMap::new(); + for w in words { + first_char_to_word + .entry(w.chars().next().unwrap()) + .or_insert(vec![]) + .push(w); + } + + let mut result = Vec::new(); + + for (rown, row) in board.iter().enumerate() { + for (column, ch) in row.iter().enumerate() { + if let Some(possible_words) = first_char_to_word.get(ch) { + for word in possible_words { + if search( + rown, + column, + board, + &word.chars().skip(1).collect::>(), + ) { + result.push(word.to_owned().to_owned().to_owned()); + } + } + } + } + } + + result +} + +fn search(row: usize, column: usize, board: &[Vec], word: &[char]) -> bool { + if word.is_empty() { + return true; + } + let (first_char, other_chars) = word.split_first().unwrap(); + + if row > 0 { + if let Some(char_row) = board.get(row - 1) { + if char_row.get(column).unwrap() == first_char + && search(row - 1, column, board, other_chars) + { + return true; + } + } + } + if let Some(char_row) = board.get(row + 1) { + if char_row.get(column).unwrap() == first_char + && search(row + 1, column, board, other_chars) + { + return true; + } + } + if let Some(char_row) = board.get(row) { + if column > 0 + && char_row.get(column - 1).unwrap() == first_char + && search(row, column - 1, board, other_chars) + { + return true; + } + if column + 1 < char_row.len() + && char_row.get(column + 1).unwrap() == first_char + && search(row, column + 1, board, other_chars) + { + return true; + } + } + + false +} diff --git a/Week-04/Day-28_Word-Search/day28/src/main.rs b/Week-04/Day-28_Word-Search/day28/src/main.rs new file mode 100644 index 0000000..c950972 --- /dev/null +++ b/Week-04/Day-28_Word-Search/day28/src/main.rs @@ -0,0 +1,40 @@ +use std::io::{self, Write}; + +use day28::word_search; + +fn main() { + let mut buffer = String::new(); + let mut board = Vec::new(); + + println!("Insert the characters of the rows without any space (press enter alone to stop creating the board): "); + + loop { + print!("Row: "); + io::stdout().flush().expect("Failed to flush stdout"); + + io::stdin() + .read_line(&mut buffer) + .expect("Failed to read line"); + + if buffer.trim().is_empty() { + break; + } + + board.push(buffer.trim().chars().collect()); + buffer.clear(); + } + + buffer.clear(); + + print!("Insert the words separated by a space: "); + io::stdout().flush().expect("Failed to flush stdout"); + + io::stdin() + .read_line(&mut buffer) + .expect("Failed to read line"); + + let words: Vec<&str> = buffer.split_whitespace().collect(); + + let result = word_search(&board, &words); + println!("Words in the board: {:?}", result); +} diff --git a/Week-04/Day-28_Word-Search/day28/tests/example.rs b/Week-04/Day-28_Word-Search/day28/tests/example.rs new file mode 100644 index 0000000..f5a7654 --- /dev/null +++ b/Week-04/Day-28_Word-Search/day28/tests/example.rs @@ -0,0 +1,20 @@ +#[cfg(test)] +mod example { + use day28::word_search; + + #[test] + fn example() { + assert_eq!( + word_search( + &[ + vec!['o', 'a', 'a', 'n'], + vec!['e', 't', 'a', 'e'], + vec!['i', 'h', 'k', 'r'], + vec!['i', 'f', 'l', 'v'] + ], + &["oath", "pea", "eat", "rain"] + ), + ["oath", "eat"] + ) + } +}