diff --git a/common/src/itertools.rs b/common/src/itertools.rs deleted file mode 100644 index 1f8db0ef..00000000 --- a/common/src/itertools.rs +++ /dev/null @@ -1,65 +0,0 @@ -use itertools::Itertools; - -pub fn _power_set(collection: C) -> Vec> -where - C: IntoIterator, - T: Clone, -{ - power_set_impl(collection, true) -} - -pub fn power_set_without_empty(collection: C) -> Vec> -where - C: IntoIterator, - T: Clone, -{ - power_set_impl(collection, false) -} - -fn power_set_impl(collection: C, include_empty_set: bool) -> Vec> -where - C: IntoIterator, - T: Clone, -{ - let vec = collection.into_iter().collect_vec(); - - // https://en.wikipedia.org/wiki/Power_set#Properties - let mut result = Vec::with_capacity(2usize.checked_pow(vec.len() as u32).expect("Overflow")); - - let start = if include_empty_set { 0 } else { 1 }; - - for i in start..=vec.len() { - result.extend(vec.iter().cloned().combinations(i)); - } - - result -} - -#[cfg(test)] -mod tests { - use super::{_power_set, power_set_without_empty}; - use crate::instrament; - use rstest::rstest; - - instrament! { - #[rstest] - fn test_power_set( - #[values(vec![], vec![1], vec![1, 2], vec![1, 2, 3])] - collection: Vec - ) (|data: &TestPowerSet| { - let result = _power_set(collection.clone()); - insta::assert_yaml_snapshot!(data.to_string(), result); - }) - } - - instrament! { - #[rstest] - fn test_power_set_without_empty( - #[values(vec![], vec![1], vec![1, 2], vec![1, 2, 3])] - collection: Vec - ) (|data: &TestPowerSetWithoutEmpty| { - let result = power_set_without_empty(collection.clone()); - insta::assert_yaml_snapshot!(data.to_string(), result); - }) - } -} diff --git a/common/src/lib.rs b/common/src/lib.rs index 1a7b6d25..4f9f181f 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -1,6 +1,5 @@ #![allow(clippy::cargo_common_metadata)] pub mod instrament; -pub mod itertools; pub mod lookup; pub mod strings; diff --git a/common/src/snapshots/common__itertools__tests__test_power_set-[].snap b/common/src/snapshots/common__itertools__tests__test_power_set-[].snap deleted file mode 100644 index e3509d37..00000000 --- a/common/src/snapshots/common__itertools__tests__test_power_set-[].snap +++ /dev/null @@ -1,8 +0,0 @@ ---- -source: common/src/itertools.rs -expression: result -info: - collection: [] ---- -- [] - diff --git a/common/src/snapshots/common__itertools__tests__test_power_set-[_1,_2,_3,_].snap b/common/src/snapshots/common__itertools__tests__test_power_set-[_1,_2,_3,_].snap deleted file mode 100644 index 76dfc05e..00000000 --- a/common/src/snapshots/common__itertools__tests__test_power_set-[_1,_2,_3,_].snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: common/src/itertools.rs -expression: result -info: - collection: - - 1 - - 2 - - 3 ---- -- [] -- - 1 -- - 2 -- - 3 -- - 1 - - 2 -- - 1 - - 3 -- - 2 - - 3 -- - 1 - - 2 - - 3 - diff --git a/common/src/snapshots/common__itertools__tests__test_power_set-[_1,_2,_].snap b/common/src/snapshots/common__itertools__tests__test_power_set-[_1,_2,_].snap deleted file mode 100644 index 162673a7..00000000 --- a/common/src/snapshots/common__itertools__tests__test_power_set-[_1,_2,_].snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: common/src/itertools.rs -expression: result -info: - collection: - - 1 - - 2 ---- -- [] -- - 1 -- - 2 -- - 1 - - 2 - diff --git a/common/src/snapshots/common__itertools__tests__test_power_set-[_1,_].snap b/common/src/snapshots/common__itertools__tests__test_power_set-[_1,_].snap deleted file mode 100644 index d7475bba..00000000 --- a/common/src/snapshots/common__itertools__tests__test_power_set-[_1,_].snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: common/src/itertools.rs -expression: result -info: - collection: - - 1 ---- -- [] -- - 1 - diff --git a/common/src/snapshots/common__itertools__tests__test_power_set_without_empty-[].snap b/common/src/snapshots/common__itertools__tests__test_power_set_without_empty-[].snap deleted file mode 100644 index eab078b8..00000000 --- a/common/src/snapshots/common__itertools__tests__test_power_set_without_empty-[].snap +++ /dev/null @@ -1,8 +0,0 @@ ---- -source: common/src/itertools.rs -expression: result -info: - collection: [] ---- -[] - diff --git a/common/src/snapshots/common__itertools__tests__test_power_set_without_empty-[_1,_2,_3,_].snap b/common/src/snapshots/common__itertools__tests__test_power_set_without_empty-[_1,_2,_3,_].snap deleted file mode 100644 index e3f80f14..00000000 --- a/common/src/snapshots/common__itertools__tests__test_power_set_without_empty-[_1,_2,_3,_].snap +++ /dev/null @@ -1,22 +0,0 @@ ---- -source: common/src/itertools.rs -expression: result -info: - collection: - - 1 - - 2 - - 3 ---- -- - 1 -- - 2 -- - 3 -- - 1 - - 2 -- - 1 - - 3 -- - 2 - - 3 -- - 1 - - 2 - - 3 - diff --git a/common/src/snapshots/common__itertools__tests__test_power_set_without_empty-[_1,_2,_].snap b/common/src/snapshots/common__itertools__tests__test_power_set_without_empty-[_1,_2,_].snap deleted file mode 100644 index b1182346..00000000 --- a/common/src/snapshots/common__itertools__tests__test_power_set_without_empty-[_1,_2,_].snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: common/src/itertools.rs -expression: result -info: - collection: - - 1 - - 2 ---- -- - 1 -- - 2 -- - 1 - - 2 - diff --git a/common/src/snapshots/common__itertools__tests__test_power_set_without_empty-[_1,_].snap b/common/src/snapshots/common__itertools__tests__test_power_set_without_empty-[_1,_].snap deleted file mode 100644 index 68971d6e..00000000 --- a/common/src/snapshots/common__itertools__tests__test_power_set_without_empty-[_1,_].snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: common/src/itertools.rs -expression: result -info: - collection: - - 1 ---- -- - 1 - diff --git a/core/src/stages/german/driver.rs b/core/src/stages/german/driver.rs index ea5fed66..5760c7c2 100644 --- a/core/src/stages/german/driver.rs +++ b/core/src/stages/german/driver.rs @@ -8,9 +8,9 @@ use crate::stages::{ }; use cached::proc_macro::cached; use cached::SizedCache; -use common::itertools::power_set_without_empty; use common::lookup::binary_search_uneven; use common::strings::{is_compound_word, titlecase}; +use itertools::Itertools; use log::{debug, trace}; static VALID_GERMAN_WORDS: &str = include_str!(concat!(env!("OUT_DIR"), "/de.txt")); // Generated in `build.rs`. @@ -339,14 +339,34 @@ impl Stage for GermanStage { } fn find_valid_replacement(word: &str, replacements: &[Replacement]) -> Option { - let replacement_combinations = power_set_without_empty(replacements.iter().copied()); + let replacement_combinations: Vec> = replacements + .iter() + .powerset() + .map(|v| v.into_iter().copied().collect()) + .collect(); + debug!("Starting search for valid replacement for word '{}'", word); trace!( "All replacement combinations to try: {:?}", replacement_combinations ); - for replacements in replacement_combinations { + // By definition, the power set contains the empty set. There are two options for + // handling it: + // - not skipping: empty set is tried first, and if that word is valid, it is + // returned + // - skipping: empty set is skipped, *some* replacements will take place; if none of + // them are valid, no replacements will take place + // + // Not skipping it means words like `Busse` will remain unchanged on first + // iteration. Then, `Busse` will turn out to be valid already and will be returned . + // Skipping it means `Buße` is tried, which is *also* valid and returned, foregoing + // `Busse`. + debug_assert!(replacement_combinations + .first() + .map_or(true, std::vec::Vec::is_empty)); + + for replacements in replacement_combinations.into_iter().skip(1) { let mut candidate = word.to_owned(); candidate.apply_replacements(replacements); trace!(