Refactoring

master
Inga 🏳‍🌈 7 years ago
parent 5ffaa1090a
commit 5a0026ff80
  1. 41
      dotnet/WhiteRabbit/Program.cs
  2. 20
      dotnet/WhiteRabbit/StringsProcessor.cs

@ -24,11 +24,10 @@
stopwatch.Start();
var sourcePhrase = ConfigurationManager.AppSettings["SourcePhrase"];
var sourceChars = ToOrderedChars(sourcePhrase);
var maxWordsInPhrase = int.Parse(ConfigurationManager.AppSettings["MaxWordsInPhrase"]);
if (sourceChars.Length + maxWordsInPhrase > 28)
if (sourcePhrase.Where(ch => ch != ' ').Count() + maxWordsInPhrase > 28)
{
Console.WriteLine("Only anagrams of up to 27 characters (including whitespace) are allowed");
return;
@ -78,27 +77,14 @@
stopwatch.Restart();
processor.CheckPhrases(phraseSet => ProcessPhraseSet(phraseSet, expectedHashesFirstComponents, stopwatch));
Console.WriteLine($"Done; time from start: {stopwatch.Elapsed}");
}
private static void ProcessPhraseSet(PhraseSet phraseSet, Vector<uint> expectedHashesFirstComponents, Stopwatch stopwatch)
{
phraseSet.ComputeMD5();
for (var i = 0; i < Constants.PhrasesPerSet; i++)
processor.CheckPhrases(expectedHashesFirstComponents, (phraseBytes, hashFirstComponent) =>
{
/*Debug.Assert(
sourceChars == ToOrderedChars(ToString(phraseSet, i)),
$"StringsProcessor produced incorrect anagram: {ToString(phraseSet, i)}");*/
var phrase = Encoding.ASCII.GetString(phraseBytes);
var hash = ComputeFullMD5(phraseBytes);
Console.WriteLine($"Found phrase for {hash} ({hashFirstComponent:x8}): {phrase}; time from start is {stopwatch.Elapsed}");
});
if (Vector.EqualsAny(expectedHashesFirstComponents, new Vector<uint>(phraseSet.GetMD5(i))))
{
var phrase = ToString(phraseSet, i);
var hash = ComputeFullMD5(phrase);
Console.WriteLine($"Found phrase for {hash} ({phraseSet.GetMD5(i):x8}): {phrase}; time from start is {stopwatch.Elapsed}");
}
}
Console.WriteLine($"Done; time from start: {stopwatch.Elapsed}");
}
// Code taken from http://stackoverflow.com/a/321404/831314
@ -112,9 +98,8 @@
}
// We can afford to spend some time here; this code will only run for matched phrases (and for one in several billion non-matched)
private static string ComputeFullMD5(string phrase)
private static string ComputeFullMD5(byte[] phraseBytes)
{
var phraseBytes = Encoding.ASCII.GetBytes(phrase);
using (var hashAlgorithm = new MD5CryptoServiceProvider())
{
var resultBytes = hashAlgorithm.ComputeHash(phraseBytes);
@ -127,11 +112,6 @@
return hex.Substring(6, 2) + hex.Substring(4, 2) + hex.Substring(2, 2) + hex.Substring(0, 2);
}
private static string ToString(PhraseSet phrase, int offset)
{
return Encoding.ASCII.GetString(phrase.GetBytes(offset));
}
private static IEnumerable<byte[]> ReadInput()
{
string line;
@ -140,10 +120,5 @@
yield return Encoding.ASCII.GetBytes(line);
}
}
private static string ToOrderedChars(string source)
{
return new string(source.Where(ch => ch != ' ').OrderBy(ch => ch).ToArray());
}
}
}

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
internal sealed class StringsProcessor
@ -60,13 +61,13 @@
private int NumberOfCharacters { get; }
public void CheckPhrases(Action<PhraseSet> action)
public void CheckPhrases(Vector<uint> expectedHashes, Action<byte[], uint> action)
{
// 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();
// converting sequences of vectors to the sequences of words...
Parallel.ForEach(sums, new ParallelOptions { MaxDegreeOfParallelism = Constants.NumberOfThreads }, sum => ProcessSum(sum, action));
Parallel.ForEach(sums, new ParallelOptions { MaxDegreeOfParallelism = Constants.NumberOfThreads }, sum => ProcessSum(sum, expectedHashes, action));
}
public long GetPhrasesCount()
@ -118,24 +119,31 @@
return result;
}
private void ProcessSum(int[] sum, Action<PhraseSet> action)
private void ProcessSum(int[] sum, Vector<uint> expectedHashes, Action<byte[], uint> action)
{
var initialPhraseSet = new PhraseSet();
initialPhraseSet.Init();
initialPhraseSet.FillLength(this.NumberOfCharacters, sum.Length);
var phraseSet = new PhraseSet();
phraseSet.Init();
var filter = ComputeFilter(sum);
var permutationsFilter = ComputeFilter(sum);
var wordsVariants = this.ConvertVectorsToWordIndexes(sum);
foreach (var wordsArray in Flattener.Flatten(wordsVariants))
{
//Console.WriteLine(new string(wordsArray.SelectMany(wordIndex => this.AllWords[wordIndex].Original).Select(b => (char)b).ToArray()));
var permutations = PrecomputedPermutationsGenerator.HamiltonianPermutations(wordsArray.Length, filter);
var permutations = PrecomputedPermutationsGenerator.HamiltonianPermutations(wordsArray.Length, permutationsFilter);
for (var i = 0; i < permutations.Length; i += Constants.PhrasesPerSet)
{
phraseSet.FillPhraseSet(initialPhraseSet, this.AllWords, wordsArray, permutations, i);
action(phraseSet);
phraseSet.ComputeMD5();
for (var j = 0; j < Constants.PhrasesPerSet; j++)
{
if (Vector.EqualsAny(expectedHashes, new Vector<uint>(phraseSet.GetMD5(j))))
{
action(phraseSet.GetBytes(j), phraseSet.GetMD5(j));
}
}
}
}
}

Loading…
Cancel
Save