diff --git a/WhiteRabbit/App.config b/WhiteRabbit/App.config index 8324aa6..f2af62f 100644 --- a/WhiteRabbit/App.config +++ b/WhiteRabbit/App.config @@ -1,6 +1,14 @@ - + + + + + + + + + \ No newline at end of file diff --git a/WhiteRabbit/Program.cs b/WhiteRabbit/Program.cs index e6faae4..3c354f1 100644 --- a/WhiteRabbit/Program.cs +++ b/WhiteRabbit/Program.cs @@ -5,6 +5,8 @@ using System.Diagnostics; using System.Linq; using System.Numerics; + using System.Reactive.Concurrency; + using System.Reactive.Linq; using System.Security.Cryptography; using System.Text; @@ -31,11 +33,18 @@ var expectedHashesAsVectors = new HashSet>(expectedHashes.Select(hash => new Vector(StringToByteArray(hash)))); - foreach (var result in AddHashes(processor.GeneratePhrases(ReadInput()))) + var phrases = processor.GeneratePhrases(ReadInput()); + using (var hasher = MD5.Create()) { - if (expectedHashesAsVectors.Contains(result.Item2)) + var phrasesWithHashes = phrases + .Select(phrase => new { phrase, hash = ComputeHash(hasher, phrase) }) + .SubscribeOn(NewThreadScheduler.Default); + + var filteredPhrases = phrasesWithHashes.Where(tuple => expectedHashesAsVectors.Contains(tuple.hash)); + + foreach (var result in filteredPhrases.ToEnumerable()) { - Console.WriteLine($"Found phrase: {result.Item1} (spent {stopwatch.Elapsed})"); + Console.WriteLine($"Found phrase with hash {HashToString(result.hash)}: {result.phrase} (spent {stopwatch.Elapsed})"); } } @@ -52,16 +61,14 @@ .ToArray(); } - private static IEnumerable>> AddHashes(IEnumerable input) + private static Vector ComputeHash(HashAlgorithm hasher, string phrase) { - using (MD5 hasher = MD5.Create()) - { - foreach (var line in input) - { - var data = hasher.ComputeHash(Encoding.ASCII.GetBytes(line)); - yield return Tuple.Create(line, new Vector(data)); - } - } + return new Vector(hasher.ComputeHash(Encoding.ASCII.GetBytes(phrase))); + } + + private static string HashToString(Vector hash) + { + return string.Concat(Enumerable.Range(0, 16).Select(i => hash[i].ToString("x2"))); } private static IEnumerable ReadInput() diff --git a/WhiteRabbit/StringsProcessor.cs b/WhiteRabbit/StringsProcessor.cs index 3cbe422..d8a2f50 100644 --- a/WhiteRabbit/StringsProcessor.cs +++ b/WhiteRabbit/StringsProcessor.cs @@ -1,8 +1,11 @@ namespace WhiteRabbit { + using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; + using System.Reactive.Concurrency; + using System.Reactive.Linq; internal class StringsProcessor { @@ -20,7 +23,7 @@ private VectorsProcessor VectorsProcessor { get; } - public IEnumerable GeneratePhrases(IEnumerable words) + public IObservable GeneratePhrases(IEnumerable words) { // Dictionary of vectors to array of words represented by this vector var formattedWords = words @@ -32,15 +35,17 @@ .ToDictionary(group => group.Key, group => group.Select(tuple => tuple.word).ToArray()); // task of finding anagrams could be reduced to the task of finding sequences of dictionary vectors with the target sum - var sums = this.VectorsProcessor.GenerateSequences(formattedWords.Keys); + var sums = this.VectorsProcessor.GenerateSequences(formattedWords.Keys).ObserveOn(Scheduler.Default); // converting sequences of vectors to the sequences of words... var anagramsWords = sums .Select(sum => ImmutableStack.Create(sum.Select(vector => formattedWords[vector]).ToArray())) .SelectMany(this.Flatten) - .Select(stack => stack.ToArray()); + .Select(stack => stack.ToArray()) + .SubscribeOn(NewThreadScheduler.Default); - return anagramsWords.Select(list => string.Join(" ", list)); + return anagramsWords.Select(list => string.Join(" ", list)) + .SubscribeOn(NewThreadScheduler.Default); } // Converts e.g. pair of variants [[a, b, c], [d, e]] into all possible pairs: [[a, d], [a, e], [b, d], [b, e], [c, d], [c, e]] diff --git a/WhiteRabbit/VectorsProcessor.cs b/WhiteRabbit/VectorsProcessor.cs index 28be0c6..4dedc7f 100644 --- a/WhiteRabbit/VectorsProcessor.cs +++ b/WhiteRabbit/VectorsProcessor.cs @@ -6,6 +6,8 @@ using System.Diagnostics; using System.Linq; using System.Numerics; + using System.Reactive.Concurrency; + using System.Reactive.Linq; internal class VectorsProcessor { @@ -33,12 +35,18 @@ private long Iterations { get; set; } = 0; // Produces all sequences of vectors with the target sum - public IEnumerable[]> GenerateSequences(IEnumerable> vectors) + public IObservable[]> GenerateSequences(IReadOnlyCollection> vectors) { var filteredVectors = this.FilterVectors(vectors); var dictionary = ImmutableStack.Create(filteredVectors.ToArray()); - var unorderedSequences = this.GenerateUnorderedSequences(this.Target, ImmutableStack.Create>(), dictionary); - var allSequences = unorderedSequences.SelectMany(this.GeneratePermutations); + + var unorderedSequences = this.GenerateUnorderedSequences(this.Target, ImmutableStack.Create>(), dictionary) + .ToObservable() + .SubscribeOn(NewThreadScheduler.Default); + + var allSequences = unorderedSequences + .SelectMany(this.GeneratePermutations) + .SubscribeOn(NewThreadScheduler.Default); return allSequences; } @@ -59,7 +67,7 @@ return weight; } - private IEnumerable> FilterVectors(IEnumerable> vectors) + private IEnumerable> FilterVectors(IReadOnlyCollection> vectors) { return vectors .Where(vector => ((this.Target - vector) & Negative) == Vector.Zero) diff --git a/WhiteRabbit/WhiteRabbit.csproj b/WhiteRabbit/WhiteRabbit.csproj index 1af7ec9..f2662e5 100644 --- a/WhiteRabbit/WhiteRabbit.csproj +++ b/WhiteRabbit/WhiteRabbit.csproj @@ -45,12 +45,34 @@ ..\packages\System.Numerics.Vectors.4.3.0\lib\net46\System.Numerics.Vectors.dll True + + ..\packages\System.Reactive.Core.3.1.1\lib\net46\System.Reactive.Core.dll + True + + + ..\packages\System.Reactive.Interfaces.3.1.1\lib\net45\System.Reactive.Interfaces.dll + True + + + ..\packages\System.Reactive.Linq.3.1.1\lib\net46\System.Reactive.Linq.dll + True + + + ..\packages\System.Reactive.PlatformServices.3.1.1\lib\net46\System.Reactive.PlatformServices.dll + True + + + ..\packages\System.Reactive.Windows.Threading.3.1.1\lib\net45\System.Reactive.Windows.Threading.dll + True + + + diff --git a/WhiteRabbit/packages.config b/WhiteRabbit/packages.config index d38493d..05c58a2 100644 --- a/WhiteRabbit/packages.config +++ b/WhiteRabbit/packages.config @@ -2,4 +2,10 @@ + + + + + + \ No newline at end of file