Tries. Trie trie # ( , ).
var trie = new Trie(new[] { "un", "que", "stio", "na", "ble", "qu", "es", "ti", "onable", "o", "nable" });
var word = "unquestionable";
var parts = new List<List<string>>();
Split(word, 0, trie, trie.Root, new List<string>(), parts);
public static void Split(string word, int index, Trie trie, TrieNode node, List<string> currentParts, List<List<string>> parts)
{
if (node.IsTerminal)
{
currentParts.Add(node.Word);
if (index == word.Length)
{
parts.Add(new List<string>(currentParts));
}
else
{
Split(word, index, trie, trie.Root, currentParts, parts);
}
currentParts.RemoveAt(currentParts.Count - 1);
}
if (index == word.Length)
{
return;
}
TrieNode nextNode;
if (!node.Edges.TryGetValue(word[index], out nextNode))
{
return;
}
Split(word, index + 1, trie, nextNode, currentParts, parts);
}
public class Trie
{
public readonly TrieNode Root = new TrieNode();
public Trie()
{
}
public Trie(IEnumerable<string> words)
{
this.AddRange(words);
}
public void Add(string word)
{
var currentNode = this.Root;
foreach (char ch in word)
{
TrieNode nextNode;
if (!currentNode.Edges.TryGetValue(ch, out nextNode))
{
nextNode = new TrieNode();
currentNode.Edges[ch] = nextNode;
}
currentNode = nextNode;
}
currentNode.Word = word;
}
public void AddRange(IEnumerable<string> words)
{
foreach (var word in words)
{
this.Add(word);
}
}
}
public class TrieNode
{
public readonly Dictionary<char, TrieNode> Edges = new Dictionary<char, TrieNode>();
public string Word { get; set; }
public bool IsTerminal
{
get
{
return this.Word != null;
}
}
}
word - , parts (, List<string[]>, . parts.Add(new List<string>(currentParts)); parts.Add(currentParts.ToArray()); List<List<string>> List<string[]>.
Enigmativity, , , , , . , +1, . , . "" Trie (s): -)
Func<string, bool> isSyllable = t => Regex.IsMatch(t, "^(un|que|stio|na|ble|qu|es|ti|onable|o|nable)$");
Func<string, IEnumerable<string[]>> splitter = null;
splitter =
t =>
(
from n in Enumerable.Range(1, t.Length - 1)
let s = t.Substring(0, n)
where isSyllable(s)
let e = t.Substring(n)
let f = splitter(e)
from g in f
select (new[] { s }).Concat(g).ToArray()
)
.Concat(isSyllable(t) ? new[] { new string[] { t } } : new string[0][]);
var parts = splitter(word).ToList();
:
from n in Enumerable.Range(1, t.Length - 1)
let s = t.Substring(0, n)
where isSyllable(s)
, 1 - 1 , . . .
let e = t.Substring(n)
let f = splitter(e)
from g in f
select (new[] { s }).Concat(g).ToArray()
"" . , . , IEnumerable<IEnumerable<string>>, ToArray.
( , let,
from g in splitter(t.Substring(n))
select (new[] { s }).Concat(g).ToArray()
)
"" .
.Concat(isSyllable(t) ? new[] { new string[] { t } } : new string[0][]);
, Concat , ( - isSyllable(t) ? new[] { new string[] { t } }.Concat(oldLambdaFunction) : oldLambdaFunction)
, , . Concat ( no Concat)