anagram_logger now manipulates SIMD vectors instead of strings

main
Inga 🏳‍🌈 3 years ago
parent 956c550998
commit 69edfe4e14
  1. 51
      src/anagram_logger.rs
  2. 14
      src/dictionary_builder.rs
  3. 3
      src/main.rs

@ -1,55 +1,38 @@
use packed_simd::u8x32;
use crate::dictionary_builder::Dictionary; use crate::dictionary_builder::Dictionary;
use crate::dictionary_builder::WordInfo; use crate::dictionary_builder::WordInfo;
use crate::permutations_cache::PermutationsCache; use crate::permutations_cache::PermutationsCache;
pub fn get_anagram_view(anagram: &Vec<usize>, dictionary: &Dictionary) -> String { fn get_anagram_view_from_simd(simd_vector: u8x32, phrase_length: usize) -> String {
anagram.iter() let mut string_bytes: [u8; 32] = [0; 32];
.map(|&index| { simd_vector.write_to_slice_unaligned(&mut string_bytes);
let word_options = &dictionary.words[index];
if word_options.len() == 1 { String::from_utf8_lossy(&string_bytes[0..phrase_length]).into_owned()
word_options[0].word.clone()
} else {
format!("[{}]", word_options.iter().map(|word_info| word_info.word.clone()).collect::<Vec<_>>().join(","))
}
})
.collect::<Vec<_>>()
.join(" ")
} }
fn generate_substitutions<T: Copy>(simple_dictionary: &[Vec<T>], remaining_length: usize) -> Vec<Vec<T>> { fn generate_vector_substitutions<'a>(simple_dictionary: &'a Vec<Vec<&WordInfo>>, permutation: &'a [usize], current_phrase: u8x32, current_phrase_length: usize) -> Box<dyn Iterator<Item = u8x32> + 'a> {
if remaining_length == 0 { if permutation.len() == 0 {
return vec![Vec::new()]; return Box::new(std::iter::once(current_phrase.clone()));
} }
return simple_dictionary[remaining_length - 1].iter() let result = simple_dictionary[permutation[0]].iter()
.flat_map(|&value| { .flat_map(move |&word_info| {
generate_substitutions(simple_dictionary, remaining_length - 1).into_iter() 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()
.map(move |mut partial_substitution| { });
partial_substitution.push(value); return Box::new(result);
partial_substitution
})
})
.collect();
} }
pub fn log_anagrams(anagram_vector: &Vec<usize>, dictionary: &Dictionary, permutations: &PermutationsCache) -> () { pub fn log_anagrams(anagram_vector: &Vec<usize>, dictionary: &Dictionary, permutations: &PermutationsCache, phrase_length: usize) -> () {
let simple_vector: Vec<usize> = (0..anagram_vector.len()).collect(); let simple_vector: Vec<usize> = (0..anagram_vector.len()).collect();
let simple_dictionary: Vec<Vec<&WordInfo>> = (0..anagram_vector.len()) let simple_dictionary: Vec<Vec<&WordInfo>> = (0..anagram_vector.len())
.map(|i| dictionary.words[anagram_vector[i]].iter().map(|word_info| word_info).collect()) .map(|i| dictionary.words[anagram_vector[i]].iter().map(|word_info| word_info).collect())
.collect(); .collect();
let substitutions: Vec<Vec<&WordInfo>> = generate_substitutions::<&WordInfo>(&simple_dictionary, simple_dictionary.len());
permutations.get_permuted_vectors(&simple_vector).iter() permutations.get_permuted_vectors(&simple_vector).iter()
.flat_map(|permuted_vector| { .flat_map(|permuted_vector| {
substitutions.iter().map(move |substitution| { generate_vector_substitutions(&simple_dictionary, &permuted_vector, u8x32::splat(0), 0)
permuted_vector.iter().map(|&index| substitution[index]).collect::<Vec<_>>()
})
}) })
.for_each(|anagram| { .for_each(|anagram| {
let phrase = anagram.iter() println!("{}", get_anagram_view_from_simd(anagram, phrase_length));
.map(|word_info| word_info.word.clone())
.collect::<Vec<_>>()
.join(" ");
println!("{}", phrase);
}) })
} }

@ -1,9 +1,9 @@
use std::collections::HashMap; use std::collections::HashMap;
use packed_simd; use packed_simd::u8x32;
use crate::vector_alphabet; use crate::vector_alphabet;
pub struct WordInfo { pub struct WordInfo {
simd_words: [packed_simd::u8x32; 32], simd_words: [u8x32; 32],
pub length: usize, pub length: usize,
pub word: String, pub word: String,
} }
@ -18,10 +18,10 @@ impl WordInfo {
byte_array[32 + i] = bytes[i]; byte_array[32 + i] = bytes[i];
} }
let simd_word_zero: packed_simd::u8x32 = packed_simd::u8x32::from_slice_unaligned(&[0; 32]); let simd_word_zero: u8x32 = u8x32::from_slice_unaligned(&[0; 32]);
let mut simd_words: [packed_simd::u8x32; 32] = [simd_word_zero; 32]; let mut simd_words: [u8x32; 32] = [simd_word_zero; 32];
for i in 0..31 { 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 { WordInfo {
@ -30,6 +30,10 @@ impl WordInfo {
word, word,
} }
} }
pub fn get_simd_word_for_offset(&self, offset: usize) -> u8x32 {
self.simd_words[offset]
}
} }
pub struct Dictionary { pub struct Dictionary {

@ -42,9 +42,10 @@ fn main() {
for number_of_words in 1..=max_number_of_words { for number_of_words in 1..=max_number_of_words {
//println!("======= Number of words: {} =======", 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 permutations = permutations_cache::PermutationsCache::new(number_of_words);
let result = anagram_finder::find_anagrams(&dictionary, number_of_words); let result = anagram_finder::find_anagrams(&dictionary, number_of_words);
result.par_iter() 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));
} }
} }

Loading…
Cancel
Save