Implemented allowWordsReuse flag

feature-allow-words-reuse
Inga 🏳‍🌈 7 years ago
parent 4bc3e45b8d
commit 6989f478d9
  1. 1
      WhiteRabbit/App.config
  2. 2
      WhiteRabbit/Program.cs
  3. 3
      WhiteRabbit/StringsProcessor.cs
  4. 31
      WhiteRabbit/VectorsProcessor.cs

@ -6,6 +6,7 @@
<appSettings>
<add key="SourcePhrase" value="poultry outwits ants" />
<add key="MaxWordsInPhrase" value="5" />
<add key="AllowWordsReuse" value="false" />
<add key="ExpectedHashes" value="e4820b45d2277f3844eac66c903e84be,23170acc097c24edb98fc5488ab033fe,665e5bcb0c20062fe8abaaf4628bb154"/>
</appSettings>
</configuration>

@ -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}");

@ -8,7 +8,7 @@
{
private const byte SPACE = 32;
public StringsProcessor(byte[] sourceString, int maxWordsCount, IEnumerable<byte[]> words)
public StringsProcessor(byte[] sourceString, int maxWordsCount, bool allowWordsReuse, IEnumerable<byte[]> 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());
}

@ -17,7 +17,7 @@
PrecomputedPermutationsGenerator.HamiltonianPermutations(0);
}
public VectorsProcessor(Vector<byte> target, int maxVectorsCount, Vector<byte>[] dictionary)
public VectorsProcessor(Vector<byte> target, int maxVectorsCount, bool allowWordsReuse, Vector<byte>[] dictionary)
{
if (Enumerable.Range(0, Vector<byte>.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<VectorInfo> Dictionary { get; }
// Produces all sequences of vectors with the target sum
@ -43,7 +46,14 @@
public ParallelQuery<int[]> 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<ImmutableStack<int>> GenerateUnorderedSequences(Vector<byte> remainder, int remainderNorm, int allowedRemainingWords, ImmutableArray<VectorInfo> dictionary, int currentDictionaryPosition)
private static IEnumerable<ImmutableStack<int>> GenerateUnorderedSequences(Vector<byte> remainder, int remainderNorm, int allowedRemainingWords, ImmutableArray<VectorInfo> 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<VectorInfo> dictionary, int offset)
{
if (offset >= dictionary.Length)
{
return dictionary.Length;
}
var start = offset;
var end = dictionary.Length - 1;

Loading…
Cancel
Save