From 498f64b5cd2c6dee3b2aa78d64c231a5c45e798c Mon Sep 17 00:00:00 2001 From: Rorik Star Platinum Date: Thu, 4 Dec 2025 15:38:26 +0300 Subject: [PATCH] anagram --- rust/anagram/src/lib.rs | 40 +++++++++++++++++++---- rust/anagram/tests/anagram.rs | 17 ---------- rust/parallel-letter-frequency/src/lib.rs | 2 +- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/rust/anagram/src/lib.rs b/rust/anagram/src/lib.rs index f192a9f..3e626d2 100644 --- a/rust/anagram/src/lib.rs +++ b/rust/anagram/src/lib.rs @@ -1,8 +1,36 @@ -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; -pub fn anagrams_for<'a>( - word: &str, - possible_anagrams: &[&str] - ) -> HashSet<&'a str> { - todo!("For the '{word}' word find anagrams among the following words: {possible_anagrams:?}"); +pub trait CharCounter { + fn get_chars_frequency(&self) -> HashMap; +} + +pub trait AnagramsFinder<'a> { + fn find_anagrams(&self, pattern_raw: &str) -> HashSet<&'a str>; +} + +impl CharCounter for str { + fn get_chars_frequency(&self) -> HashMap { + self.chars().fold(HashMap::new(), |mut acc, c| { + *acc.entry(c).or_insert(0) += 1; + acc + }) + } +} + +impl<'a> AnagramsFinder<'a> for [&'a str] { + fn find_anagrams(&self, pattern_raw: &str) -> HashSet<&'a str> { + let pattern = pattern_raw.to_lowercase(); + let pattern_map: HashMap = pattern.get_chars_frequency(); + self.iter() + .copied() + .filter(|word_raw| { + let word = word_raw.to_lowercase(); + word != pattern && word.get_chars_frequency() == pattern_map + }) + .collect() + } +} + +pub fn anagrams_for<'a>(word: &str, possible_anagrams: &[&'a str]) -> HashSet<&'a str> { + possible_anagrams.find_anagrams(word) } diff --git a/rust/anagram/tests/anagram.rs b/rust/anagram/tests/anagram.rs index 5814f69..e6d606d 100644 --- a/rust/anagram/tests/anagram.rs +++ b/rust/anagram/tests/anagram.rs @@ -11,7 +11,6 @@ fn no_matches() { } #[test] -#[ignore] fn detects_two_anagrams() { let word = "solemn"; let inputs = &["lemons", "cherry", "melons"]; @@ -21,7 +20,6 @@ fn detects_two_anagrams() { } #[test] -#[ignore] fn does_not_detect_anagram_subsets() { let word = "good"; let inputs = &["dog", "goody"]; @@ -31,7 +29,6 @@ fn does_not_detect_anagram_subsets() { } #[test] -#[ignore] fn detects_anagram() { let word = "listen"; let inputs = &["enlists", "google", "inlets", "banana"]; @@ -41,7 +38,6 @@ fn detects_anagram() { } #[test] -#[ignore] fn detects_three_anagrams() { let word = "allergy"; let inputs = &[ @@ -58,7 +54,6 @@ fn detects_three_anagrams() { } #[test] -#[ignore] fn detects_multiple_anagrams_with_different_case() { let word = "nose"; let inputs = &["Eons", "ONES"]; @@ -68,7 +63,6 @@ fn detects_multiple_anagrams_with_different_case() { } #[test] -#[ignore] fn does_not_detect_non_anagrams_with_identical_checksum() { let word = "mass"; let inputs = &["last"]; @@ -78,7 +72,6 @@ fn does_not_detect_non_anagrams_with_identical_checksum() { } #[test] -#[ignore] fn detects_anagrams_case_insensitively() { let word = "Orchestra"; let inputs = &["cashregister", "Carthorse", "radishes"]; @@ -88,7 +81,6 @@ fn detects_anagrams_case_insensitively() { } #[test] -#[ignore] fn detects_anagrams_using_case_insensitive_subject() { let word = "Orchestra"; let inputs = &["cashregister", "carthorse", "radishes"]; @@ -98,7 +90,6 @@ fn detects_anagrams_using_case_insensitive_subject() { } #[test] -#[ignore] fn detects_anagrams_using_case_insensitive_possible_matches() { let word = "orchestra"; let inputs = &["cashregister", "Carthorse", "radishes"]; @@ -108,7 +99,6 @@ fn detects_anagrams_using_case_insensitive_possible_matches() { } #[test] -#[ignore] fn does_not_detect_an_anagram_if_the_original_word_is_repeated() { let word = "go"; let inputs = &["goGoGO"]; @@ -118,7 +108,6 @@ fn does_not_detect_an_anagram_if_the_original_word_is_repeated() { } #[test] -#[ignore] fn anagrams_must_use_all_letters_exactly_once() { let word = "tapper"; let inputs = &["patter"]; @@ -128,7 +117,6 @@ fn anagrams_must_use_all_letters_exactly_once() { } #[test] -#[ignore] fn words_are_not_anagrams_of_themselves() { let word = "BANANA"; let inputs = &["BANANA"]; @@ -138,7 +126,6 @@ fn words_are_not_anagrams_of_themselves() { } #[test] -#[ignore] fn words_are_not_anagrams_of_themselves_even_if_letter_case_is_partially_different() { let word = "BANANA"; let inputs = &["Banana"]; @@ -148,7 +135,6 @@ fn words_are_not_anagrams_of_themselves_even_if_letter_case_is_partially_differe } #[test] -#[ignore] fn words_are_not_anagrams_of_themselves_even_if_letter_case_is_completely_different() { let word = "BANANA"; let inputs = &["banana"]; @@ -158,7 +144,6 @@ fn words_are_not_anagrams_of_themselves_even_if_letter_case_is_completely_differ } #[test] -#[ignore] fn words_other_than_themselves_can_be_anagrams() { let word = "LISTEN"; let inputs = &["LISTEN", "Silent"]; @@ -168,7 +153,6 @@ fn words_other_than_themselves_can_be_anagrams() { } #[test] -#[ignore] fn handles_case_of_greek_letters() { let word = "ΑΒΓ"; let inputs = &["ΒΓΑ", "ΒΓΔ", "γβα", "αβγ"]; @@ -178,7 +162,6 @@ fn handles_case_of_greek_letters() { } #[test] -#[ignore] fn different_characters_may_have_the_same_bytes() { let word = "a⬂"; let inputs = &["€a"]; diff --git a/rust/parallel-letter-frequency/src/lib.rs b/rust/parallel-letter-frequency/src/lib.rs index 49f86e9..2a98d23 100644 --- a/rust/parallel-letter-frequency/src/lib.rs +++ b/rust/parallel-letter-frequency/src/lib.rs @@ -11,7 +11,7 @@ pub fn frequency(input: &[&str], worker_count: usize) -> HashMap { thread::scope(|s| { let chunk_size = input.len().div_ceil(worker_count); - let mut handles: Vec<_> = input + let handles: Vec<_> = input .chunks(chunk_size) .map(|chunk| { s.spawn(move || {