根据模式

时间:2016-03-09 18:54:24

标签: c# linq pattern-matching combinations populate

我试图解密一个单词,其中的字母已经被随机的其他字母替换(但不是2个不同的字母进入同一个字母)。

目标:
我正在寻找一个长度和字母模式已知的单词。

我所知道的:
模式本身意味着搜索"来宾"我知道" 123454"它显示了这个单词中唯一字母的位置。当然,我知道它的英文单词写得正确。

软件方面:
我创建了一个DataGridView标题按标题标题。我希望使用所有字母Column的可能组合填充每个a-z(模式)。

我尝试了什么:
从最后开始=>我成功实施了一个拼写检查程序。所以最后我想到了通过列并检查每个结果以找到实际的单词。

从我看到的起点到目前为止我已写过:

private string[] alpha = new string[] { "a", "b", "c", ..."z"};
private int[] digits = new int[] { 0, 1, 2, 3, 4,....9 };

private void bruteforce()
{
    // Each Column
    foreach(DataGridViewColumn col in dgvResults.Columns)
    {
        // HeaderText to CharArray to IntArray (-48 to switch from ASCII to INT).
        int[] pattern = Array.ConvertAll(col.HeaderText.ToCharArray(), c => c - 48);

        // Prepare an result-array with the same length as the pattern.
        string[] resultSet = Enumerable.Repeat("-", pattern.Length).ToArray();

        // For each digit 0-9.
        foreach(int digit in digits)
        {
            // In pattern search for each digit and save the index.
            int[] indexes = pattern.FindAllIndexof(digit);
            // If index is found.
            if(indexes.Length > 0)
            {
                // Custom function ReplaceAtIndex. 
                // Replace resultSet-Values at given Indexes with unique letter
                resultSet.ReplaceAtIndex(indexes, alpha[digit]);
            }
        }
    }
}

当前结果:
0112344 的模式将被保存为resultSet abbcdee 。 现在我需要在保持相同模式的同时循环字母。

这一步感觉比以前更复杂。我想,在继续吹走我的脑袋之前,我会看看是否有一些天才的人在stackoverflow上可以提供更简单的方法(也许是LINQ的一些快捷方式)。

所以,请问,是否有人在思考"轻松做事"关于谁可以帮助我? 我很感激这里的每一个帮助。感谢

1 个答案:

答案 0 :(得分:2)

IMO是一个非常有效的算法,用于生成您要求的内容。

它是我在Looking at each combination in jagged arraySystem.OutOfMemoryException when generating permutations中使用的算法的变体,并经过优化以执行最低分配。

public static class Algorithms
{
    private static readonly char[] alpha = Enumerable.Range('a', 'z' - 'a' + 1).Select(c => (char)c).ToArray();

    public static IEnumerable<string> GenerateWords(this string pattern)
    {
        return pattern.GenerateWordsCore().Select(word => new string(word));
    }

    public static IEnumerable<char[]> GenerateWordsCore(this string pattern)
    {
        var distinctSet = pattern.Select(c => c - '0').Distinct().ToArray();
        var indexMap = pattern.Select(c => Array.IndexOf(distinctSet, c - '0')).ToArray();
        var result = new char[pattern.Length];
        var indices = new int[distinctSet.Length];
        var indexUsed = new bool[alpha.Length];
        for (int pos = 0, index = 0; ;)
        {
            // Generate the next permutation
            if (index < alpha.Length)
            {
                if (indexUsed[index]) { index++; continue; }
                indices[pos] = index;
                indexUsed[index] = true;
                if (++pos < distinctSet.Length) { index = 0; continue; }
                // Populate and yield the result
                for (int i = 0; i < indexMap.Length; i++)
                    result[i] = alpha[indices[indexMap[i]]];
                yield return result;
            }
            // Advance to next permutation if any
            if (pos == 0) yield break;
            index = indices[--pos];
            indexUsed[index] = false;
            index++;
        }
    }
}

样本用法:

bool test = "12334".GenerateWords().Contains("hello");
foreach (var word in "123454".GenerateWords())
{
    // Do something with word
}