diff --git a/src/anagram_logger.rs b/src/anagram_logger.rs index 5374367..13f91ca 100644 --- a/src/anagram_logger.rs +++ b/src/anagram_logger.rs @@ -1,55 +1,38 @@ +use packed_simd::u8x32; use crate::dictionary_builder::Dictionary; use crate::dictionary_builder::WordInfo; use crate::permutations_cache::PermutationsCache; -pub fn get_anagram_view(anagram: &Vec, dictionary: &Dictionary) -> String { - anagram.iter() - .map(|&index| { - let word_options = &dictionary.words[index]; - if word_options.len() == 1 { - word_options[0].word.clone() - } else { - format!("[{}]", word_options.iter().map(|word_info| word_info.word.clone()).collect::>().join(",")) - } - }) - .collect::>() - .join(" ") +fn get_anagram_view_from_simd(simd_vector: u8x32, phrase_length: usize) -> String { + let mut string_bytes: [u8; 32] = [0; 32]; + simd_vector.write_to_slice_unaligned(&mut string_bytes); + + String::from_utf8_lossy(&string_bytes[0..phrase_length]).into_owned() } -fn generate_substitutions(simple_dictionary: &[Vec], remaining_length: usize) -> Vec> { - if remaining_length == 0 { - return vec![Vec::new()]; +fn generate_vector_substitutions<'a>(simple_dictionary: &'a Vec>, permutation: &'a [usize], current_phrase: u8x32, current_phrase_length: usize) -> Box + 'a> { + if permutation.len() == 0 { + return Box::new(std::iter::once(current_phrase.clone())); } - return simple_dictionary[remaining_length - 1].iter() - .flat_map(|&value| { - generate_substitutions(simple_dictionary, remaining_length - 1).into_iter() - .map(move |mut partial_substitution| { - partial_substitution.push(value); - partial_substitution - }) - }) - .collect(); + let result = simple_dictionary[permutation[0]].iter() + .flat_map(move |&word_info| { + generate_vector_substitutions(&simple_dictionary, &permutation[1..], current_phrase ^ word_info.get_simd_word_for_offset(current_phrase_length), current_phrase_length + word_info.length + 1).into_iter() + }); + return Box::new(result); } -pub fn log_anagrams(anagram_vector: &Vec, dictionary: &Dictionary, permutations: &PermutationsCache) -> () { +pub fn log_anagrams(anagram_vector: &Vec, dictionary: &Dictionary, permutations: &PermutationsCache, phrase_length: usize) -> () { let simple_vector: Vec = (0..anagram_vector.len()).collect(); let simple_dictionary: Vec> = (0..anagram_vector.len()) .map(|i| dictionary.words[anagram_vector[i]].iter().map(|word_info| word_info).collect()) .collect(); - let substitutions: Vec> = generate_substitutions::<&WordInfo>(&simple_dictionary, simple_dictionary.len()); permutations.get_permuted_vectors(&simple_vector).iter() .flat_map(|permuted_vector| { - substitutions.iter().map(move |substitution| { - permuted_vector.iter().map(|&index| substitution[index]).collect::>() - }) + generate_vector_substitutions(&simple_dictionary, &permuted_vector, u8x32::splat(0), 0) }) .for_each(|anagram| { - let phrase = anagram.iter() - .map(|word_info| word_info.word.clone()) - .collect::>() - .join(" "); - println!("{}", phrase); + println!("{}", get_anagram_view_from_simd(anagram, phrase_length)); }) } \ No newline at end of file diff --git a/src/dictionary_builder.rs b/src/dictionary_builder.rs index ec403f7..7846d3b 100644 --- a/src/dictionary_builder.rs +++ b/src/dictionary_builder.rs @@ -1,9 +1,9 @@ use std::collections::HashMap; -use packed_simd; +use packed_simd::u8x32; use crate::vector_alphabet; pub struct WordInfo { - simd_words: [packed_simd::u8x32; 32], + simd_words: [u8x32; 32], pub length: usize, pub word: String, } @@ -18,10 +18,10 @@ impl WordInfo { byte_array[32 + i] = bytes[i]; } - let simd_word_zero: packed_simd::u8x32 = packed_simd::u8x32::from_slice_unaligned(&[0; 32]); - let mut simd_words: [packed_simd::u8x32; 32] = [simd_word_zero; 32]; + let simd_word_zero: u8x32 = u8x32::from_slice_unaligned(&[0; 32]); + let mut simd_words: [u8x32; 32] = [simd_word_zero; 32]; for i in 0..31 { - simd_words[i] = packed_simd::u8x32::from_slice_unaligned(&byte_array[32-i..64-i]); + simd_words[i] = u8x32::from_slice_unaligned(&byte_array[32-i..64-i]); } WordInfo { @@ -30,6 +30,10 @@ impl WordInfo { word, } } + + pub fn get_simd_word_for_offset(&self, offset: usize) -> u8x32 { + self.simd_words[offset] + } } pub struct Dictionary { diff --git a/src/main.rs b/src/main.rs index 3d78c42..0847f61 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,9 +42,10 @@ fn main() { for number_of_words in 1..=max_number_of_words { //println!("======= Number of words: {} =======", number_of_words); + let phrase_length = phrase_byte_length_without_spaces + number_of_words - 1; let permutations = permutations_cache::PermutationsCache::new(number_of_words); let result = anagram_finder::find_anagrams(&dictionary, number_of_words); result.par_iter() - .for_each(|anagram_vector| anagram_logger::log_anagrams(anagram_vector, &dictionary, &permutations)); + .for_each(|anagram_vector| anagram_logger::log_anagrams(anagram_vector, &dictionary, &permutations, phrase_length)); } }