diff --git a/src/problem/mod.rs b/src/problem/mod.rs index 6f67282..288ee4e 100644 --- a/src/problem/mod.rs +++ b/src/problem/mod.rs @@ -125,4 +125,5 @@ mod p289_game_of_life; mod p383_ransom_note; mod p290_word_pattern; mod p205_isomorphic_strings; -mod p242_valid_anagram; \ No newline at end of file +mod p242_valid_anagram; +mod p49_group_anagrams; \ No newline at end of file diff --git a/src/problem/p49_group_anagrams.rs b/src/problem/p49_group_anagrams.rs new file mode 100644 index 0000000..02d4540 --- /dev/null +++ b/src/problem/p49_group_anagrams.rs @@ -0,0 +1,107 @@ +/** + * [49] Group Anagrams + */ +pub struct Solution {} + +// submission codes start here +use std::{collections::HashMap, hash::Hash}; + +#[derive(Debug)] +struct WordState { + characters: HashMap, +} + +impl PartialEq for WordState { + fn eq(&self, other: &Self) -> bool { + if self.characters.len() != other.characters.len() { + return false; + } + + for (c, &v) in self.characters.iter() { + match other.characters.get(c) { + Some(other_v) => { + if *other_v != v { + return false; + } + } + None => { + return false; + } + } + } + + true + } +} + +impl Eq for WordState {} + +impl Hash for WordState { + fn hash(&self, state: &mut H) { + let mut chars: Vec<(&char, &usize)> = + self.characters.iter().map(|p| p).collect(); + + chars.sort_by_key(|p| p.0); + + for (&c, &v) in chars { + c.hash(state); + v.hash(state); + } + } +} + +impl Solution { + pub fn group_anagrams(strs: Vec) -> Vec> { + let mut result = HashMap::with_capacity(strs.len()); + + for word in strs { + let mut characters = HashMap::with_capacity(26); + + for c in word.chars() { + let entry = characters.entry(c).or_insert(0); + *entry += 1; + } + + let state = WordState { characters }; + dbg!(&state); + let entry = result.entry(state).or_insert(vec![]); + entry.push(word); + } + + result.into_values().collect() + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_49() { + assert_eq!( + WordState { + characters: HashMap::from([('e', 1), ('a', 1), ('t', 1)]) + }, + WordState { + characters: HashMap::from([('a', 1), ('t', 1), ('e', 1)]) + } + ); + assert_eq!( + vec![ + vec!["bat".to_owned()], + vec!["nat".to_owned(), "tan".to_owned()], + vec!["ate".to_owned(), "eat".to_owned(), "tea".to_owned()] + ], + Solution::group_anagrams(vec![ + "eat".to_owned(), + "tea".to_owned(), + "tan".to_owned(), + "ate".to_owned(), + "nat".to_owned(), + "bat".to_owned() + ]) + ); + } +}