diff --git a/source/lib.rs b/source/lib.rs index b7992e7..7708af6 100644 --- a/source/lib.rs +++ b/source/lib.rs @@ -2,3 +2,4 @@ pub mod longest_common_prefix; pub mod palindrome_number; pub mod reverse_integer; pub mod two_sum; +pub mod valid_parenthesis; diff --git a/source/valid_parenthesis/mod.rs b/source/valid_parenthesis/mod.rs new file mode 100644 index 0000000..321c3af --- /dev/null +++ b/source/valid_parenthesis/mod.rs @@ -0,0 +1,55 @@ +pub fn is_valid(string: String) -> bool { + // If the input string is of an odd length it cannot be valid, since every + // opening character must also have a closing one. + if string.len() % 2 != 0 { + return false; + } + + fn get_closing_character(character: char) -> char { + match character { + '[' => ']', + '{' => '}', + '(' => ')', + _ => panic!("Invalid input character: {character}"), + } + } + + let mut stack = vec![]; + + for character in string.chars() { + match character { + // For any opening characters, add their counterpart to the stack and move + // on to the next character in the string. + '[' | '{' | '(' => stack.push(get_closing_character(character)), + + // For any other characters, get the most recent character we've seen and + // if it doesn't equal the expected closing character then the string is + // invalid. + _ => { + if character != stack.pop().unwrap_or_default() { + return false; + } + } + }; + } + + // After the string has been looped over, if anything is left in the stack the + // string is invalid. + stack.len() == 0 +} + +#[test] +fn test_valid_parenthesis() { + assert!(is_valid("".to_string())); + assert!(is_valid("[]".to_string())); + assert!(is_valid("[()]".to_string())); + assert!(is_valid("[{}()]".to_string())); + + assert!(!is_valid("[".to_string())); + assert!(!is_valid("[()".to_string())); + assert!(!is_valid("((".to_string())); + + assert!(!is_valid("[)".to_string())); + assert!(!is_valid("[(}]".to_string())); + assert!(!is_valid("([{}()]}".to_string())); +}