From 6989f478d9d629ae81d307cef0c3ee02e4b2d8a8 Mon Sep 17 00:00:00 2001
From: inga-lovinde <52715130+inga-lovinde@users.noreply.github.com>
Date: Wed, 22 Mar 2017 09:44:51 +0300
Subject: [PATCH] Implemented allowWordsReuse flag
---
WhiteRabbit/App.config | 1 +
WhiteRabbit/Program.cs | 2 ++
WhiteRabbit/StringsProcessor.cs | 3 ++-
WhiteRabbit/VectorsProcessor.cs | 31 +++++++++++++++++++++++++++----
4 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/WhiteRabbit/App.config b/WhiteRabbit/App.config
index 6566d25..29df439 100644
--- a/WhiteRabbit/App.config
+++ b/WhiteRabbit/App.config
@@ -6,6 +6,7 @@
+
diff --git a/WhiteRabbit/Program.cs b/WhiteRabbit/Program.cs
index 843d076..e8ed761 100644
--- a/WhiteRabbit/Program.cs
+++ b/WhiteRabbit/Program.cs
@@ -27,6 +27,7 @@
var sourceChars = ToOrderedChars(sourcePhrase);
var maxWordsInPhrase = int.Parse(ConfigurationManager.AppSettings["MaxWordsInPhrase"]);
+ var allowWordsReuse = bool.Parse(ConfigurationManager.AppSettings["AllowWordsReuse"]);
var expectedHashesAsVectors = ConfigurationManager.AppSettings["ExpectedHashes"]
.Split(',')
@@ -40,6 +41,7 @@
var processor = new StringsProcessor(
Encoding.ASCII.GetBytes(sourcePhrase),
maxWordsInPhrase,
+ allowWordsReuse,
ReadInput());
Console.WriteLine($"Initialization complete; time from start: {stopwatch.Elapsed}");
diff --git a/WhiteRabbit/StringsProcessor.cs b/WhiteRabbit/StringsProcessor.cs
index dc50d6c..0a36731 100644
--- a/WhiteRabbit/StringsProcessor.cs
+++ b/WhiteRabbit/StringsProcessor.cs
@@ -8,7 +8,7 @@
{
private const byte SPACE = 32;
- public StringsProcessor(byte[] sourceString, int maxWordsCount, IEnumerable words)
+ public StringsProcessor(byte[] sourceString, int maxWordsCount, bool allowWordsReuse, IEnumerable words)
{
var filteredSource = sourceString.Where(ch => ch != SPACE).ToArray();
this.NumberOfCharacters = filteredSource.Length;
@@ -29,6 +29,7 @@
this.VectorsProcessor = new VectorsProcessor(
this.VectorsConverter.GetVector(filteredSource).Value,
maxWordsCount,
+ allowWordsReuse,
vectorsToWords.Select(tuple => tuple.vector).ToArray());
}
diff --git a/WhiteRabbit/VectorsProcessor.cs b/WhiteRabbit/VectorsProcessor.cs
index 7eb61a3..6316e8f 100644
--- a/WhiteRabbit/VectorsProcessor.cs
+++ b/WhiteRabbit/VectorsProcessor.cs
@@ -17,7 +17,7 @@
PrecomputedPermutationsGenerator.HamiltonianPermutations(0);
}
- public VectorsProcessor(Vector target, int maxVectorsCount, Vector[] dictionary)
+ public VectorsProcessor(Vector target, int maxVectorsCount, bool allowWordsReuse, Vector[] dictionary)
{
if (Enumerable.Range(0, Vector.Count).Any(i => target[i] > MaxComponentValue))
{
@@ -27,6 +27,7 @@
this.Target = target;
this.MaxVectorsCount = maxVectorsCount;
+ this.AllowWordsReuseAddendum = allowWordsReuse ? 0 : 1;
this.Dictionary = ImmutableArray.Create(FilterVectors(dictionary, target).ToArray());
}
@@ -34,6 +35,8 @@
private int MaxVectorsCount { get; }
+ private int AllowWordsReuseAddendum { get; }
+
private ImmutableArray Dictionary { get; }
// Produces all sequences of vectors with the target sum
@@ -43,7 +46,14 @@
public ParallelQuery GenerateSequences()
#endif
{
- return GenerateUnorderedSequences(this.Target, GetVectorNorm(this.Target, this.Target), this.MaxVectorsCount, this.Dictionary, 0)
+ var unorderedSequences = GenerateUnorderedSequences(
+ this.Target,
+ GetVectorNorm(this.Target, this.Target),
+ this.MaxVectorsCount,
+ this.Dictionary,
+ 0,
+ this.AllowWordsReuseAddendum);
+ return unorderedSequences
#if !SINGLE_THREADED
.AsParallel()
#endif
@@ -81,7 +91,7 @@
// In every sequence, next vector always goes after the previous one from dictionary.
// E.g. if dictionary is [x, y, z], then only [x, y] sequence could be generated, and [y, x] will never be generated.
// That way, the complexity of search goes down by a factor of MaxVectorsCount! (as if [x, y] does not add up to a required target, there is no point in checking [y, x])
- private static IEnumerable> GenerateUnorderedSequences(Vector remainder, int remainderNorm, int allowedRemainingWords, ImmutableArray dictionary, int currentDictionaryPosition)
+ private static IEnumerable> GenerateUnorderedSequences(Vector remainder, int remainderNorm, int allowedRemainingWords, ImmutableArray dictionary, int currentDictionaryPosition, int dictionaryPositionAddendum)
{
if (allowedRemainingWords > 1)
{
@@ -106,7 +116,15 @@
{
var newRemainder = remainder - currentVectorInfo.Vector;
var newRemainderNorm = remainderNorm - currentVectorInfo.Norm;
- foreach (var result in GenerateUnorderedSequences(newRemainder, newRemainderNorm, newAllowedRemainingWords, dictionary, i))
+ var newSequences = GenerateUnorderedSequences(
+ newRemainder,
+ newRemainderNorm,
+ newAllowedRemainingWords,
+ dictionary,
+ i + dictionaryPositionAddendum,
+ dictionaryPositionAddendum);
+
+ foreach (var result in newSequences)
{
yield return result.Push(currentVectorInfo.Index);
}
@@ -133,6 +151,11 @@
// BCL BinarySearch would find any vector with required norm, not the first one; or would find nothing if there is no such vector
private static int FindFirstWithNormLessOrEqual(int expectedNorm, ImmutableArray dictionary, int offset)
{
+ if (offset >= dictionary.Length)
+ {
+ return dictionary.Length;
+ }
+
var start = offset;
var end = dictionary.Length - 1;