Skip to content

Commit

Permalink
Add problem 2018: Check if Word Can Be Placed In Crossword
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Jul 19, 2024
1 parent 601943b commit 7a06122
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1484,6 +1484,7 @@ pub mod problem_2011_final_value_of_variable_after_performing_operations;
pub mod problem_2012_sum_of_beauty_in_the_array;
pub mod problem_2016_maximum_difference_between_increasing_elements;
pub mod problem_2017_grid_game;
pub mod problem_2018_check_if_word_can_be_placed_in_crossword;
pub mod problem_2022_convert_1d_array_into_2d_array;
pub mod problem_2023_number_of_pairs_of_strings_with_concatenation_equal_to_target;
pub mod problem_2024_maximize_the_confusion_of_an_exam;
Expand Down
44 changes: 44 additions & 0 deletions src/problem_2018_check_if_word_can_be_placed_in_crossword/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
pub mod recursive;

pub trait Solution {
fn place_word_in_crossword(board: Vec<Vec<char>>, word: String) -> bool;
}

#[cfg(test)]
mod tests {
use super::Solution;

pub fn run<S: Solution>() {
let test_cases = [
((&["# #", " #", "#c "] as &[_], "abc"), true),
((&[" #a", " #c", " #a"], "ac"), false),
((&["# #", " #", "# c"], "ca"), true),
((&[" #o tmo # "], "octmor"), true),
((&["# #", "# #", "# c"], "ca"), true),
((&[" ", " "], "a"), false),
((&[" cz", "###"], "cz"), false),
(
(
&[
" ", " ", " ", " ", "#", "#", " ", "b", "#", " ", " ", " ", " ", " ", " ", " ", " ", "c", " ",
"#",
],
"ba",
),
true,
),
((&["c #", "###"], "ab"), false),
((&[" ", "#", "o", " ", "t", "m", "o", " ", "#", " "], "octmor"), true),
];

for ((board, word), expected) in test_cases {
assert_eq!(
S::place_word_in_crossword(
board.iter().map(|row| row.chars().collect()).collect(),
word.to_string(),
),
expected,
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
pub struct Solution;

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl Solution {
fn check(mut line_iter: impl Iterator<Item = u8>, word: &[u8], tag: u8) -> bool {
'outer: loop {
let mut word_iter = word.iter().copied();

loop {
let c = word_iter.next();

if let Some(pattern) = line_iter.next() {
match pattern {
b' ' => {
if c.is_some() {
continue;
}
}
b'#' => {
if c.is_none() {
return true;
}

break;
}
_ => {
if c == Some(pattern) {
continue;
}
}
}
} else {
return c.is_none();
}

loop {
match line_iter.next() {
None => return false,
Some(b'#') => continue 'outer,
_ => {}
}
}
}
}
}

pub fn place_word_in_crossword(board: Vec<Vec<char>>, word: String) -> bool {
let rows = board.len();
let columns = board.first().map_or(0, Vec::len);
let mut flat_board = Vec::with_capacity(columns * rows);

for row in board {
flat_board.extend(row.into_iter().map(|c| c as u8));
}

let word = word.as_bytes();

for row in flat_board.chunks_exact(columns) {
if Self::check(row.iter().copied(), word, 0) || Self::check(row.iter().copied().rev(), word, 1) {
return true;
}
}

let mut iter = flat_board.iter().copied();

for _ in 0..columns {
let column_iter = iter.clone().step_by(columns);

if Self::check(column_iter.clone(), word, 2) || Self::check(column_iter.rev(), word, 3) {
return true;
}

iter.next();
}

false
}
}

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl super::Solution for Solution {
fn place_word_in_crossword(board: Vec<Vec<char>>, word: String) -> bool {
Self::place_word_in_crossword(board, word)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}

0 comments on commit 7a06122

Please sign in to comment.