use std::collections::HashMap; use std::collections::HashSet; use std::sync::{LazyLock, Mutex}; #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] pub enum Op { Multiply, Add, } type OperatorCache = HashMap>>; static OPERATOR_SET_CACHE: LazyLock> = LazyLock::new(|| Mutex::new(HashMap::new())); fn check_operator_set_cache(cache_key: usize) -> Option>> { OPERATOR_SET_CACHE.lock().unwrap().get(&cache_key).cloned() } fn store_operator_set_in_cache(cache_key: usize, cache_value: HashSet>) { OPERATOR_SET_CACHE .lock() .unwrap() .insert(cache_key, cache_value); } fn create_operator_set_recurse( operators_permutation_set: &mut HashSet>, operators: Vec, ) { operators_permutation_set.insert(operators.clone()); if !operators.contains(&Op::Add) { return; } for i in 0..operators.len() { if operators[i] == Op::Multiply { break; } let mut new_operators = operators.clone(); new_operators[i] = Op::Multiply; create_operator_set_recurse(operators_permutation_set, new_operators); } } pub fn create_operator_set(num_of_operators: usize) -> HashSet> { // Check cache if let Some(cached_value) = check_operator_set_cache(num_of_operators) { return cached_value.clone(); } let mut operator_sets: HashSet> = HashSet::new(); create_operator_set_recurse(&mut operator_sets, vec![Op::Add; num_of_operators]); // Store value in cache store_operator_set_in_cache(num_of_operators, operator_sets.clone()); operator_sets } fn create_permutations_recurse( values: &HashSet, len: usize, permutations: &mut HashSet>, curr_permutation: Vec, ) { if curr_permutation.len() == len { permutations.insert(curr_permutation); return; } for v in values { let mut next_permutation = curr_permutation.clone(); next_permutation.push(*v); create_permutations_recurse(values, len, permutations, next_permutation); } } pub fn create_permutations(set: HashSet, len: usize) -> HashSet> { let mut permutations = HashSet::new(); create_permutations_recurse(&set, len, &mut permutations, vec![]); permutations }