Words are now byte arrays instead of strings

plinq
Inga 🏳‍🌈 7 years ago
parent e153e20cc6
commit 2bb80c719a
  1. 39
      WhiteRabbit/ByteArrayEqualityComparer.cs
  2. 18
      WhiteRabbit/Program.cs
  3. 29
      WhiteRabbit/StringsProcessor.cs
  4. 10
      WhiteRabbit/VectorsConverter.cs
  5. 1
      WhiteRabbit/WhiteRabbit.csproj

@ -0,0 +1,39 @@
namespace WhiteRabbit
{
using System.Collections.Generic;
using System.Linq;
internal class ByteArrayEqualityComparer : IEqualityComparer<byte[]>
{
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;
}
}
}

@ -13,6 +13,10 @@
/// </summary>
public static class Program
{
const string SourcePhrase = "poultry outwits ants";
const int MaxWordsInPhrase = 4;
/// <summary>
/// Main entry point
/// </summary>
@ -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<Tuple<string, Vector<byte>>> AddHashes(IEnumerable<string> input)
private static IEnumerable<Tuple<byte[], Vector<byte>>> AddHashes(IEnumerable<byte[]> 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<byte>(data));
}
}
}
private static IEnumerable<string> ReadInput()
private static IEnumerable<byte[]> ReadInput()
{
string line;
while ((line = Console.ReadLine()) != null)
{
yield return line;
yield return Encoding.ASCII.GetBytes(line);
}
//System.Threading.Thread.Sleep(10000);
}
}
}

@ -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<string> GeneratePhrases(IEnumerable<string> words)
public IEnumerable<byte[]> GeneratePhrases(IEnumerable<byte[]> 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;
}
}
}

@ -10,18 +10,18 @@
/// </summary>
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<char, int> CharToInt { get; }
private Dictionary<byte, int> CharToInt { get; }
private char[] IntToChar { get; }
private byte[] IntToChar { get; }
public Vector<byte>? GetVector(string word)
public Vector<byte>? GetVector(byte[] word)
{
if (word.Any(ch => !this.CharToInt.ContainsKey(ch)))
{
@ -39,7 +39,7 @@
public string GetString(Vector<byte> 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());
}
}
}

@ -53,6 +53,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ByteArrayEqualityComparer.cs" />
<Compile Include="PrecomputedPermutationsGenerator.cs" />
<Compile Include="PermutationsGenerator.cs" />
<Compile Include="StringsProcessor.cs" />

Loading…
Cancel
Save