diff --git a/README.md b/README.md index 44f7c47..507d6ab 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,10 @@ Performance This solution is not optimized for multi-threading. -Nevertheless, it can find the original phrase of up to 4 words for any hash in less than 3 minutes on Sandy Bridge @2.8GHz. +Nevertheless, the performance on Sandy Bridge @2.8GHz is as follows: + +* If only phrases of at most 3 words are allowed, then it takes 2.5 seconds to find and check all anagrams; all relevant hashes are solved in first 0.4 seconds; + +* If phrases of 4 words are allowed as well, then it takes 70 seconds to find and check all anagrams; all hashes are solved in first 5 seconds; + +For comparison, certain other solutions available on GitHub seem to require 3 hours to find all 3-word anagrams (i.e. this solution is faster by a factor of 4000 in 3-word case). \ No newline at end of file diff --git a/WhiteRabbit/VectorsProcessor.cs b/WhiteRabbit/VectorsProcessor.cs index 1514d79..28be0c6 100644 --- a/WhiteRabbit/VectorsProcessor.cs +++ b/WhiteRabbit/VectorsProcessor.cs @@ -43,10 +43,27 @@ return allSequences; } + // We want words with more letters (and among these, words with more "rare" letters) to appear first, to reduce the searching time somewhat. + // Applying such a sort, we reduce the total number of triplets to check for anagrams from ~62M to ~29M. + // Total number of quadruplets is reduced from 1468M to mere 311M. + // Also, it produces the intended results faster (as these are more likely to contain longer words - e.g. "poultry outwits ants" is more likely than "p o u l t r y o u t w i t s a n t s"). + // This method basically gives us the 1-norm of the vector in the space rescaled so that the target is [1, 1, ..., 1]. + private int GetVectorWeight(Vector vector) + { + var weight = 0; + for (var i = 0; this.Target[i] != 0; i++) + { + weight += (720 * vector[i]) / this.Target[i]; // 720 = 6!, so that the result will be a whole number (unless Target[i] > 6) + } + + return weight; + } + private IEnumerable> FilterVectors(IEnumerable> vectors) { return vectors - .Where(vector => ((this.Target - vector) & Negative) == Vector.Zero); + .Where(vector => ((this.Target - vector) & Negative) == Vector.Zero) + .OrderBy(GetVectorWeight); } [Conditional("DEBUG")]