From 1327814fd1c4eb190494f366dc58c919da5497e4 Mon Sep 17 00:00:00 2001 From: inga-lovinde <52715130+inga-lovinde@users.noreply.github.com> Date: Tue, 21 Mar 2017 14:45:27 +0300 Subject: [PATCH] Implemented all anagrams output in debug mode --- WhiteRabbit/Program.cs | 55 ++++++++++++++++++++++++++------- WhiteRabbit/StringsProcessor.cs | 7 +++-- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/WhiteRabbit/Program.cs b/WhiteRabbit/Program.cs index 32dbb6e..978d8ed 100644 --- a/WhiteRabbit/Program.cs +++ b/WhiteRabbit/Program.cs @@ -1,6 +1,7 @@ namespace WhiteRabbit { using System; + using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -15,7 +16,7 @@ { private const string SourcePhrase = "poultry outwits ants"; - private const int MaxWordsInPhrase = 4; + private const int MaxWordsInPhrase = 5; /// /// Main entry point @@ -34,24 +35,51 @@ var expectedHashesAsVectors = expectedHashes.Select(hash => new Vector(HexadecimalStringToByteArray(hash))).ToArray(); + var anagramsBag = new ConcurrentBag(); + var sourceChars = ToOrderedChars(SourcePhrase); + var processor = new StringsProcessor(Encoding.ASCII.GetBytes(SourcePhrase), MaxWordsInPhrase, ReadInput()); Console.WriteLine($"Initialization complete; time from start: {stopwatch.Elapsed}"); + processor.GeneratePhrases() + .ForAll(phraseBytes => + { + Debug.Assert( + sourceChars == ToOrderedChars(Encoding.ASCII.GetString(phraseBytes)), + $"StringsProcessor produced incorrect anagram: {Encoding.ASCII.GetString(phraseBytes)}"); + + var hashVector = ComputeHashVector(phraseBytes); + if (Array.IndexOf(expectedHashesAsVectors, hashVector) >= 0) + { + var phrase = Encoding.ASCII.GetString(phraseBytes); + var hash = VectorToHexadecimalString(hashVector); + Console.WriteLine($"Found phrase for {hash}: {phrase}; time from start is {stopwatch.Elapsed}"); + } + #if DEBUG - // it makes the program slow (as all anagrams are generated twice), but this code is only run in a debug mode - var totalAnagramsCount = processor.GeneratePhrases().Count(); - Console.WriteLine($"Total anagrams count: {totalAnagramsCount}; time from start: {stopwatch.Elapsed}"); + anagramsBag.Add(Encoding.ASCII.GetString(phraseBytes)); #endif + }); - processor.GeneratePhrases() - .Select(phraseBytes => new { phraseBytes, hashVector = ComputeHashVector(phraseBytes) }) - .Where(tuple => Array.IndexOf(expectedHashesAsVectors, tuple.hashVector) >= 0) - .Select(tuple => new { phrase = Encoding.ASCII.GetString(tuple.phraseBytes), hash = VectorToHexadecimalString(tuple.hashVector) }) - .ForAll(phraseInfo => Console.WriteLine($"Found phrase for {phraseInfo.hash}: {phraseInfo.phrase}; time from start is {stopwatch.Elapsed}")); - - stopwatch.Stop(); Console.WriteLine($"Done; time from start: {stopwatch.Elapsed}"); + +#if DEBUG + var anagramsArray = anagramsBag.ToArray(); + var anagramsSet = new HashSet(anagramsArray); + Array.Sort(anagramsArray); + + Console.WriteLine("All anagrams:"); + for (var i = 0; i < anagramsArray.Length; i++) + { + Console.WriteLine(anagramsArray[i]); + } + + // Duplicate anagrams are expected, as e.g. "norway spoils tut tut" will be taken twice: + // as "norway1 spoils2 tut3 tut4" and "norway1 spoils2 tut4 tut3" + // (in addition to e.g. "norway1 tut3 spoils2 tut4") + Console.WriteLine($"Total anagrams count: {anagramsArray.Length}; unique anagrams: {anagramsSet.Count}; time from start: {stopwatch.Elapsed}"); +#endif } // Code taken from http://stackoverflow.com/a/321404/831314 @@ -87,6 +115,11 @@ } } + private static string ToOrderedChars(string source) + { + return new string(source.Where(ch => ch != ' ').OrderBy(ch => ch).ToArray()); + } + #if SINGLE_THREADED private static void ForAll(this IEnumerable source, Action action) { diff --git a/WhiteRabbit/StringsProcessor.cs b/WhiteRabbit/StringsProcessor.cs index a870da2..dc50d6c 100644 --- a/WhiteRabbit/StringsProcessor.cs +++ b/WhiteRabbit/StringsProcessor.cs @@ -2,14 +2,15 @@ { using System; using System.Collections.Generic; - using System.Collections.Immutable; using System.Linq; internal sealed class StringsProcessor { + private const byte SPACE = 32; + public StringsProcessor(byte[] sourceString, int maxWordsCount, IEnumerable words) { - var filteredSource = sourceString.Where(ch => ch != 32).ToArray(); + var filteredSource = sourceString.Where(ch => ch != SPACE).ToArray(); this.NumberOfCharacters = filteredSource.Length; this.VectorsConverter = new VectorsConverter(filteredSource); @@ -79,7 +80,7 @@ var position = currentWord.Length; for (var i = 1; i < words.Length; i++) { - result[position] = 32; + result[position] = SPACE; position++; currentWord = words[i];