From 2bb80c719a90355ff03185966a2937b589593e16 Mon Sep 17 00:00:00 2001 From: inga-lovinde <52715130+inga-lovinde@users.noreply.github.com> Date: Fri, 10 Mar 2017 09:40:12 +0300 Subject: [PATCH] Words are now byte arrays instead of strings --- WhiteRabbit/ByteArrayEqualityComparer.cs | 39 ++++++++++++++++++++++++ WhiteRabbit/Program.cs | 18 +++++++---- WhiteRabbit/StringsProcessor.cs | 29 +++++++++++++++--- WhiteRabbit/VectorsConverter.cs | 10 +++--- WhiteRabbit/WhiteRabbit.csproj | 1 + 5 files changed, 81 insertions(+), 16 deletions(-) create mode 100644 WhiteRabbit/ByteArrayEqualityComparer.cs diff --git a/WhiteRabbit/ByteArrayEqualityComparer.cs b/WhiteRabbit/ByteArrayEqualityComparer.cs new file mode 100644 index 0000000..cedfa1e --- /dev/null +++ b/WhiteRabbit/ByteArrayEqualityComparer.cs @@ -0,0 +1,39 @@ +namespace WhiteRabbit +{ + using System.Collections.Generic; + using System.Linq; + + internal class ByteArrayEqualityComparer : IEqualityComparer + { + public bool Equals(byte[] x, byte[] y) + { + if (object.ReferenceEquals(x, y)) + { + return true; + } + + if (x?.Length != y?.Length) + { + return false; + } + + return Enumerable.Range(0, x.Length).All(i => x[i] == y[i]); + } + + public int GetHashCode(byte[] obj) + { + if (obj == null) + { + return 0; + } + + int result = 0; + for (var i = 0; i < obj.Length; i++) + { + result = unchecked(result + (i * obj[i])); + } + + return result; + } + } +} diff --git a/WhiteRabbit/Program.cs b/WhiteRabbit/Program.cs index e6faae4..11af2e3 100644 --- a/WhiteRabbit/Program.cs +++ b/WhiteRabbit/Program.cs @@ -13,6 +13,10 @@ /// public static class Program { + const string SourcePhrase = "poultry outwits ants"; + + const int MaxWordsInPhrase = 4; + /// /// Main entry point /// @@ -21,7 +25,7 @@ var stopwatch = new Stopwatch(); stopwatch.Start(); - var processor = new StringsProcessor("poultry outwits ants", 4); + var processor = new StringsProcessor(Encoding.ASCII.GetBytes(SourcePhrase), MaxWordsInPhrase); var expectedHashes = new[] { "e4820b45d2277f3844eac66c903e84be", @@ -35,7 +39,7 @@ { if (expectedHashesAsVectors.Contains(result.Item2)) { - Console.WriteLine($"Found phrase: {result.Item1} (spent {stopwatch.Elapsed})"); + Console.WriteLine($"Found phrase: {Encoding.ASCII.GetString(result.Item1)} (spent {stopwatch.Elapsed})"); } } @@ -52,25 +56,27 @@ .ToArray(); } - private static IEnumerable>> AddHashes(IEnumerable input) + private static IEnumerable>> AddHashes(IEnumerable input) { using (MD5 hasher = MD5.Create()) { foreach (var line in input) { - var data = hasher.ComputeHash(Encoding.ASCII.GetBytes(line)); + var data = hasher.ComputeHash(line); yield return Tuple.Create(line, new Vector(data)); } } } - private static IEnumerable ReadInput() + private static IEnumerable ReadInput() { string line; while ((line = Console.ReadLine()) != null) { - yield return line; + yield return Encoding.ASCII.GetBytes(line); } + + //System.Threading.Thread.Sleep(10000); } } } diff --git a/WhiteRabbit/StringsProcessor.cs b/WhiteRabbit/StringsProcessor.cs index 3cbe422..8525c0f 100644 --- a/WhiteRabbit/StringsProcessor.cs +++ b/WhiteRabbit/StringsProcessor.cs @@ -1,14 +1,15 @@ namespace WhiteRabbit { + using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; internal class StringsProcessor { - public StringsProcessor(string sourceString, int maxWordsCount) + public StringsProcessor(byte[] sourceString, int maxWordsCount) { - var filteredSource = new string(sourceString.Where(ch => ch != ' ').ToArray()); + var filteredSource = sourceString.Where(ch => ch != 32).ToArray(); this.VectorsConverter = new VectorsConverter(filteredSource); this.VectorsProcessor = new VectorsProcessor( this.VectorsConverter.GetVector(filteredSource).Value, @@ -20,11 +21,11 @@ private VectorsProcessor VectorsProcessor { get; } - public IEnumerable GeneratePhrases(IEnumerable words) + public IEnumerable GeneratePhrases(IEnumerable words) { // Dictionary of vectors to array of words represented by this vector var formattedWords = words - .Distinct() + .Distinct(new ByteArrayEqualityComparer()) .Select(word => new { word, vector = this.VectorsConverter.GetVector(word) }) .Where(tuple => tuple.vector != null) .Select(tuple => new { tuple.word, vector = tuple.vector.Value }) @@ -40,7 +41,7 @@ .SelectMany(this.Flatten) .Select(stack => stack.ToArray()); - return anagramsWords.Select(list => string.Join(" ", list)); + return anagramsWords.Select(WordsToPhrase); } // 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]] @@ -55,5 +56,23 @@ var newStack = phrase.Pop(out wordVariants); return this.Flatten(newStack).SelectMany(remainder => wordVariants.Select(word => remainder.Push(word))); } + + private byte[] WordsToPhrase(byte[][] words) + { + var result = new byte[words.Length + words.Sum(word => word.Length) - 1]; + + Buffer.BlockCopy(words[0], 0, result, 0, words[0].Length); + var position = words[0].Length; + for (var i = 1; i < words.Length; i++) + { + result[position] = 32; + position++; + + Buffer.BlockCopy(words[i], 0, result, position, words[i].Length); + position += words[i].Length; + } + + return result; + } } } diff --git a/WhiteRabbit/VectorsConverter.cs b/WhiteRabbit/VectorsConverter.cs index 8c16d7f..491c4ae 100644 --- a/WhiteRabbit/VectorsConverter.cs +++ b/WhiteRabbit/VectorsConverter.cs @@ -10,18 +10,18 @@ /// internal class VectorsConverter { - public VectorsConverter(string sourceString) + public VectorsConverter(byte[] sourceString) { var rawNumberOfOccurrences = sourceString.GroupBy(ch => ch).ToDictionary(group => group.Key, group => group.Count()); this.IntToChar = rawNumberOfOccurrences.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Key).ToArray(); this.CharToInt = Enumerable.Range(0, this.IntToChar.Length).ToDictionary(i => this.IntToChar[i], i => i); } - private Dictionary CharToInt { get; } + private Dictionary CharToInt { get; } - private char[] IntToChar { get; } + private byte[] IntToChar { get; } - public Vector? GetVector(string word) + public Vector? GetVector(byte[] word) { if (word.Any(ch => !this.CharToInt.ContainsKey(ch))) { @@ -39,7 +39,7 @@ public string GetString(Vector vector) { - return new string(Enumerable.Range(0, this.IntToChar.Length).SelectMany(i => Enumerable.Repeat(this.IntToChar[i], (int)vector[i])).ToArray()); + return new string(Enumerable.Range(0, this.IntToChar.Length).SelectMany(i => Enumerable.Repeat((char)this.IntToChar[i], vector[i])).ToArray()); } } } diff --git a/WhiteRabbit/WhiteRabbit.csproj b/WhiteRabbit/WhiteRabbit.csproj index 1af7ec9..55cfa51 100644 --- a/WhiteRabbit/WhiteRabbit.csproj +++ b/WhiteRabbit/WhiteRabbit.csproj @@ -53,6 +53,7 @@ +