Refactored to use RX

rx
Inga 🏳‍🌈 7 years ago
parent e153e20cc6
commit 5fb43799af
  1. 10
      WhiteRabbit/App.config
  2. 31
      WhiteRabbit/Program.cs
  3. 13
      WhiteRabbit/StringsProcessor.cs
  4. 16
      WhiteRabbit/VectorsProcessor.cs
  5. 22
      WhiteRabbit/WhiteRabbit.csproj
  6. 6
      WhiteRabbit/packages.config

@ -1,6 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Reactive.Core" publicKeyToken="94bc3704cddfc263" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.3000.0" newVersion="3.0.3000.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -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<Vector<byte>>(expectedHashes.Select(hash => new Vector<byte>(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<Tuple<string, Vector<byte>>> AddHashes(IEnumerable<string> input)
private static Vector<byte> 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<byte>(data));
}
}
return new Vector<byte>(hasher.ComputeHash(Encoding.ASCII.GetBytes(phrase)));
}
private static string HashToString(Vector<byte> hash)
{
return string.Concat(Enumerable.Range(0, 16).Select(i => hash[i].ToString("x2")));
}
private static IEnumerable<string> ReadInput()

@ -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<string> GeneratePhrases(IEnumerable<string> words)
public IObservable<string> GeneratePhrases(IEnumerable<string> 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]]

@ -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<Vector<byte>[]> GenerateSequences(IEnumerable<Vector<byte>> vectors)
public IObservable<Vector<byte>[]> GenerateSequences(IReadOnlyCollection<Vector<byte>> vectors)
{
var filteredVectors = this.FilterVectors(vectors);
var dictionary = ImmutableStack.Create(filteredVectors.ToArray());
var unorderedSequences = this.GenerateUnorderedSequences(this.Target, ImmutableStack.Create<Vector<byte>>(), dictionary);
var allSequences = unorderedSequences.SelectMany(this.GeneratePermutations);
var unorderedSequences = this.GenerateUnorderedSequences(this.Target, ImmutableStack.Create<Vector<byte>>(), dictionary)
.ToObservable()
.SubscribeOn(NewThreadScheduler.Default);
var allSequences = unorderedSequences
.SelectMany(this.GeneratePermutations)
.SubscribeOn(NewThreadScheduler.Default);
return allSequences;
}
@ -59,7 +67,7 @@
return weight;
}
private IEnumerable<Vector<byte>> FilterVectors(IEnumerable<Vector<byte>> vectors)
private IEnumerable<Vector<byte>> FilterVectors(IReadOnlyCollection<Vector<byte>> vectors)
{
return vectors
.Where(vector => ((this.Target - vector) & Negative) == Vector<byte>.Zero)

@ -45,12 +45,34 @@
<HintPath>..\packages\System.Numerics.Vectors.4.3.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Reactive.Core, Version=3.0.3000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reactive.Core.3.1.1\lib\net46\System.Reactive.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Reactive.Interfaces, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reactive.Interfaces.3.1.1\lib\net45\System.Reactive.Interfaces.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Reactive.Linq, Version=3.0.3000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reactive.Linq.3.1.1\lib\net46\System.Reactive.Linq.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Reactive.PlatformServices, Version=3.0.3000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reactive.PlatformServices.3.1.1\lib\net46\System.Reactive.PlatformServices.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Reactive.Windows.Threading, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reactive.Windows.Threading.3.1.1\lib\net45\System.Reactive.Windows.Threading.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Windows" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="PrecomputedPermutationsGenerator.cs" />

@ -2,4 +2,10 @@
<packages>
<package id="System.Collections.Immutable" version="1.3.1" targetFramework="net46" />
<package id="System.Numerics.Vectors" version="4.3.0" targetFramework="net46" />
<package id="System.Reactive" version="3.1.1" targetFramework="net46" />
<package id="System.Reactive.Core" version="3.1.1" targetFramework="net46" />
<package id="System.Reactive.Interfaces" version="3.1.1" targetFramework="net46" />
<package id="System.Reactive.Linq" version="3.1.1" targetFramework="net46" />
<package id="System.Reactive.PlatformServices" version="3.1.1" targetFramework="net46" />
<package id="System.Reactive.Windows.Threading" version="3.1.1" targetFramework="net46" />
</packages>
Loading…
Cancel
Save