diff --git a/coverage.cmd b/coverage.cmd new file mode 100644 index 0000000..3659404 --- /dev/null +++ b/coverage.cmd @@ -0,0 +1,11 @@ +@echo off +set RUSTFLAGS=-Zinstrument-coverage +set LLVM_PROFILE_FILE=tests-%m.profraw +cargo clean +cargo test --tests +cargo profdata -- merge -sparse tests-*.profraw -o tests.profdata +cargo cov -- report --use-color --ignore-filename-regex="(registry|toolchains)" --instr-profile=tests.profdata target\debug\deps\trustpilot_challenge_rust.exe target\debug\deps\trustpilot_challenge_rust-16a5f5b3dcaa6625.exe target\debug\deps\trustpilot_challenge_rust-ad09af9137a4ac83.exe target\debug\deps\hash_computer_test-e97eaa049af7d579.exe target\debug\deps\solver_tests-5c0a8c7757425eff.exe | more +cargo cov -- show --use-color --ignore-filename-regex="(registry|toolchains)" --instr-profile=tests.profdata target\debug\deps\trustpilot_challenge_rust.exe target\debug\deps\trustpilot_challenge_rust-16a5f5b3dcaa6625.exe target\debug\deps\trustpilot_challenge_rust-ad09af9137a4ac83.exe target\debug\deps\hash_computer_test-e97eaa049af7d579.exe target\debug\deps\solver_tests-5c0a8c7757425eff.exe --show-instantiations --show-line-counts-or-regions --Xdemangler=rustfilt | more +cargo clean +del *.profraw +del *.profdata diff --git a/src/main.rs b/src/main.rs index 4a13480..9e25fbf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,5 +18,5 @@ fn main() { let solver = Solver::create_from_input_data(words, hashes_strings, max_requested_number_of_words, phrase); solver.find_solutions() - .for_each(|solution| println!("{} {}", solution.hash, solution.anagram_string)); + .for_each(|solution| println!("{} {}", solution.get_hash(), solution.anagram_string)); } diff --git a/src/solution.rs b/src/solution.rs index 8486faa..ccc80ba 100644 --- a/src/solution.rs +++ b/src/solution.rs @@ -5,19 +5,22 @@ use crate::dictionary_builder::Dictionary; #[derive(Debug)] pub struct Solution { pub anagram_string: String, - pub hash: String, } impl Solution { pub fn from_simd(simd_vector: u8x32, phrase_length: usize) -> Solution { - let anagram_string = get_anagram_string_from_simd(simd_vector, phrase_length); - let hash = format!("{:x}", md5::compute(anagram_string.as_bytes())); + let mut string_bytes: [u8; 32] = [0; 32]; + simd_vector.write_to_slice_unaligned(&mut string_bytes); + let anagram_string = String::from_utf8_lossy(&string_bytes[0..phrase_length]).into_owned(); Solution { anagram_string, - hash, } } + + pub fn get_hash(&self) -> String { + format!("{:x}", md5::compute(self.anagram_string.as_bytes())) + } } pub fn get_anagram_vector_view(anagram: &Vec, dictionary: &Dictionary) -> String { @@ -34,13 +37,6 @@ pub fn get_anagram_vector_view(anagram: &Vec, dictionary: &Dictionary) -> .join(" ") } -fn get_anagram_string_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() -} - pub fn log_anagram(simd_vector: u8x32, phrase_length: usize) -> () { - println!("{}", get_anagram_string_from_simd(simd_vector, phrase_length)); + println!("{}", Solution::from_simd(simd_vector, phrase_length).anagram_string); } diff --git a/src/vector_alphabet.rs b/src/vector_alphabet.rs index ca7c6bc..a729dd2 100644 --- a/src/vector_alphabet.rs +++ b/src/vector_alphabet.rs @@ -1,5 +1,4 @@ use std::collections::HashMap; -use std::fmt; use packed_simd; #[derive(Debug)] diff --git a/tests/solver_tests.rs b/tests/solver_tests.rs index d893a57..0bb9bbb 100644 --- a/tests/solver_tests.rs +++ b/tests/solver_tests.rs @@ -1,2 +1,48 @@ +use rayon::iter::ParallelIterator; + extern crate trustpilot_challenge_rust; -use trustpilot_challenge_rust::hash_computer; +use trustpilot_challenge_rust::solver::Solver; +/* +const WORDS: Vec = vec!["a", "b", "aa", "bb", "ab", "ba", "aaa", "bbb", "abc", "c", "ccc", "d", "dddd"]; +const HASHES: [String; _] = [ + "b2ef629aeb4deac769c3b476387c7e9f", // a b c ab c dddd + "17fd9c64127f42baeff12fba8038a7f0", // ab c dddd abc + "73b50bfa6b3b941a53f7e3ac0d99c8a5", // c ba ba c dddd + "c475a98ce0cdfcf5640f981b98d427c3", // c c ab ba dddd + "96f824d59eea869e02f0dbfa23f5676d", // dddd abc abc +]; +*/ + +fn check_solutions(max_number_of_words: usize, expected: &[&str]) -> () { + let solver = Solver::create_from_input_data( + ["a", "b", "aa", "bb", "ab", "ba", "aaa", "bbb", "abc", "c", "ccc", "d", "dddd"].iter() + .map(|&s| s.to_owned()).collect(), + [ + "b2ef629aeb4deac769c3b476387c7e9f", // a b c ab c dddd + "17fd9c64127f42baeff12fba8038a7f0", // ab c dddd abc + "73b50bfa6b3b941a53f7e3ac0d99c8a5", // c ba ba c dddd + "c475a98ce0cdfcf5640f981b98d427c3", // c c ab ba dddd + "96f824d59eea869e02f0dbfa23f5676d", // dddd abc abc + ].iter().map(|&s| s.to_owned()).collect(), + max_number_of_words, + "abcdd cbadd" + ); + let mut result: Vec<_> = solver.find_solutions() + .map(|solution| solution.anagram_string) + .collect(); + + result.sort(); + result.dedup(); + + assert_eq!(result, expected); +} + +#[test] +fn it_solves() { + check_solutions(1, &[]); + check_solutions(2, &[]); + check_solutions(3, &["dddd abc abc"]); + check_solutions(4, &["ab c dddd abc", "dddd abc abc"]); + check_solutions(5, &["ab c dddd abc", "c ba ba c dddd", "c c ab ba dddd", "dddd abc abc"]); + check_solutions(6, &["a b c ab c dddd", "ab c dddd abc", "c ba ba c dddd", "c c ab ba dddd", "dddd abc abc"]); +}