@ -3,27 +3,17 @@
using System.Collections.Generic ;
using System.Collections.Immutable ;
using System.Linq ;
using System.Numerics ;
using System.Threading.Tasks.Dataflow ;
internal class StringsProcessor
{
public StringsProcessor ( string sourceString , int maxWordsCount )
public StringsProcessor ( string sourceString , int maxWordsCount , IEnumerable < string > words )
{
var filteredSource = new string ( sourceString . Where ( ch = > ch ! = ' ' ) . ToArray ( ) ) ;
this . VectorsConverter = new VectorsConverter ( filteredSource ) ;
this . VectorsProcessor = new VectorsProcessor (
this . VectorsConverter . GetVector ( filteredSource ) . Value ,
maxWordsCount ,
this . VectorsConverter . GetString ) ;
}
private VectorsConverter VectorsConverter { get ; }
private VectorsProcessor VectorsProcessor { get ; }
public IEnumerable < string > GeneratePhrases ( IEnumerable < string > words )
{
// Dictionary of vectors to array of words represented by this vector
var formatted Words = words
this . VectorsToWords = words
. Distinct ( )
. Select ( word = > new { word , vector = this . VectorsConverter . GetVector ( word ) } )
. Where ( tuple = > tuple . vector ! = null )
@ -31,16 +21,31 @@
. GroupBy ( tuple = > tuple . vector )
. 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 ) ;
this . VectorsProcessor = new VectorsProcessor (
this . VectorsConverter . GetVector ( filteredSource ) . Value ,
maxWordsCount ,
this . VectorsToWords . Keys ,
this . VectorsConverter . GetString ) ;
}
// 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 ( ) ) ;
private VectorsProcessor VectorsProcessor { get ; }
return anagramsWords . Select ( list = > string . Join ( " " , list ) ) ;
private VectorsConverter VectorsConverter { get ; }
private Dictionary < Vector < byte > , string [ ] > VectorsToWords { get ; }
public void PostUnorderedSequences ( ITargetBlock < Vector < byte > [ ] > target )
{
this . VectorsProcessor . GenerateUnorderedSequences ( ) . WriteToTargetBlock ( target ) ;
}
public IPropagatorBlock < Vector < byte > [ ] , string > CreateUnorderedSequencesToPhrasesTransform ( )
{
return DataflowBlockHelpers . Id < Vector < byte > [ ] > ( )
. PipeMany ( this . VectorsProcessor . UnorderedSequenceToOrderedSequences )
. Pipe ( this . OrderedSequenceToWordVariants )
. PipeMany ( this . WordVariantsToFlatWords )
. Pipe ( this . FlatWordsToPhrase ) ;
}
// 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 +60,20 @@
var newStack = phrase . Pop ( out wordVariants ) ;
return this . Flatten ( newStack ) . SelectMany ( remainder = > wordVariants . Select ( word = > remainder . Push ( word ) ) ) ;
}
private ImmutableStack < string [ ] > OrderedSequenceToWordVariants ( Vector < byte > [ ] sum )
{
return ImmutableStack . CreateRange ( sum . Select ( vector = > this . VectorsToWords [ vector ] ) ) ;
}
private IEnumerable < ImmutableStack < string > > WordVariantsToFlatWords ( ImmutableStack < string [ ] > wordVariants )
{
return this . Flatten ( wordVariants ) ;
}
private string FlatWordsToPhrase ( ImmutableStack < string > words )
{
return string . Join ( " " , words ) ;
}
}
}