public string Build(IList<MoveType> moves)
        {
            var cur = new PhrasePosition {Index = -1};

            var positions = FindOrderedPositions(moves).GetEnumerator();
            if(positions.MoveNext())
                cur = positions.Current;

            var builder = new StringBuilder();
            for(int i = 0; i < moves.Count;)
            {
                if(cur.Index == i)
                {
                    builder.Append(cur.Phrase);
                    i += cur.Length;
                    if(positions.MoveNext())
                        cur = positions.Current;
                    continue;
                }
                var move = SelectMove(moves[i]);
                builder.Append(move.First());
                i++;
            }
            return builder.ToString();
        }
 private IEnumerable<PhrasePosition> FindOrderedPositions(IList<MoveType> moves)
 {
     var cur = new PhrasePosition {Index = -1, Length = 0};
     return
         PowerPhrases
             .SelectMany(phrase => FindAllPositions(moves, phrase))
             .Where(pos => pos.Index >= 0)
             .OrderBy(pos => pos.Index)
             .Where(pos =>
             {
                 var result = !PhrasePosition.Intersected(cur, pos);
                 if(result) cur = pos;
                 return result;
             });
 }
 public static bool Intersected(PhrasePosition x, PhrasePosition y)
 {
     return y.Index >= x.Index && y.Index < x.Index + x.Length || x.Index >= y.Index && x.Index < y.Index + y.Length;
 }