【问题标题】:All letter-combinations (n-items) according pattern根据模式的所有字母组合(n 项)
【发布时间】:2023-03-29 03:47:01
【问题描述】:

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

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

我所知道的:
模式本身意味着如果搜索“客人”,我知道“123454”,它显示了这个单词中唯一字母的位置。而且我肯定知道它是正确书写的英文单词。

软件方面:
我创建了一个DataGridView,其标题由模式命名。我想用所有字母a-z 的可能组合填充每个Column(模式)。

我的尝试:
生病从最后开始=> 我已经成功实现了拼写检查器。所以最后我想只是浏览这些列并检查每个结果以找到实际的单词。

到目前为止,我已经写了这篇文章:

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 的一些快捷方式)。

那么请问,有没有人认为“轻松”可以帮助我? 我感谢这里的每一个帮助。谢谢

【问题讨论】:

  • Eric Lippert 有一组关于 Producing combinations 的博客文章,可以帮助您获得 n 个字母的所有组合,然后您可以使用他的 Producing permutations 帖子获得订购 n 个字母的所有方法并将它们应用到您的模式中。

标签: c# linq pattern-matching combinations populate


【解决方案1】:

这是 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
}

【讨论】:

  • 好的。到目前为止,很好。对“12345678”的测试没有返回结果。它肯定列出了许多组合。但是有可能还剩下一些吗?如果是这样,为什么?结果计数是 1562275。我用NHuspell (english-us) 检查了拼写。我知道这个模式表明这个词有 8 个不同的字母。
  • 是的,对不起,有一个问题,我的算法正在生成组合,但你真正需要的是唯一的排列。别担心,我会调整它并发布更新。
  • foreach(string word in "1234".GenerateWords()) =&gt; if word.Contains("th") 甚至没有返回 1 个命中。 “这个”或“那个”或“那么”或“他们”呢?
  • 哦,好吧。非常感谢 :)。顺便说一句..尊重能够在这么短的时间内写下这样的代码。
  • @C4ud3x 花费的时间比预期的多,但现在应该可以了(我希望:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-29
  • 1970-01-01
  • 2013-10-27
  • 1970-01-01
  • 2012-04-26
相关资源
最近更新 更多