C#字符排列,重复大量字符

时间:2011-11-09 11:38:06

标签: c# char combinations

你好我试图通过重复给定的char数组获得所有可能的组合。 字符数组由字母组成(仅低于字母),我需要生成长度为30或更多字符的字符串。

我尝试了许多for循环的方法,但是当我尝试在char数组中获取char的所有组合时,字符串的长度超过5,我没有内存异常。

所以我创建了类似的方法,只需要前200000个字符串,然后是2000000,依此类推,这已被证明是成功的,但只有较小的长度字符串。

这是我的方法,长度为7个字符:

public static int Progress = 0;
public static ArrayList CreateRngUrl7()
        {

            ArrayList AllCombos = new ArrayList();
            int passed = 0;
            int Too = Progress + 200000;

            char[] alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToLower().ToCharArray();

            for (int i = 0; i < alpha.Length; i++)
                for (int i1 = 0; i1 < alpha.Length; i1++)
                    for (int i2 = 0; i2 < alpha.Length; i2++)
                        for (int i3 = 0; i3 < alpha.Length; i3++)
                            for (int i4 = 0; i4 < alpha.Length; i4++)
                                for (int i5 = 0; i5 < alpha.Length; i5++)
                                    for (int i6 = 0; i6 < alpha.Length; i6++)
                                {
                                    if (passed > (Too - 200000) && passed < Too)
                                    {
                                        string word = new string(new char[] { alpha[i], alpha[i1], alpha[i2], alpha[i3], alpha[i4], alpha[i5],alpha[i6] });
                                        AllCombos.Add(word);
                                    }

                                    passed++;
                                }
            if (Too >= passed)
            {
                MessageBox.Show("All combinations of RNG7 were returned");
            }
            Progress = Too;
            return AllCombos;
        }

我尝试以上面描述的方式添加30个for循环,所以我会得到长度为30的字符串,但应用程序只是挂起。有没有更好的方法来做到这一点?所有答案都将非常感谢。提前谢谢!

有人可以直接发布方法如何使用更大的legth字符串我只是想看一个例子吗?我不必存储该数据,我只需要将其与某些内容进行比较并从内存中释放它。我使用字母表例如我不需要整个字母表。问题不是需要多长时间或它会有多少组合!!!!!

2 个答案:

答案 0 :(得分:2)

你得到OutOfMemoryException,因为在循环内你分配一个字符串并将其存储在ArrayList中。字符串必须保留在内存中,直到ArrayList被垃圾收集,并且你的循环创建的字符串比你能够存储的字符串多。

如果你只是想检查一个条件的字符串,你应该把检查放在循环中:

for ( ... some crazy loop ...) {
  var word = ... create word ...
  if (!WordPassesTest(word)) {
    Console.WriteLine(word + " failed test.");
    return false;
  }
}
return true;

然后你只需要存储一个单词。当然,如果循环足够疯狂,它就不会像我们所知的那样在宇宙结束之前终止。

如果需要执行许多嵌套但类似的循环,可以使用递归来简化代码。这是一个效率不高的例子,但至少它很简单:

Char[] chars = "ABCD".ToCharArray(); 

IEnumerable<String> GenerateStrings(Int32 length) {
  if (length == 0) {
    yield return String.Empty;
    yield break;
  }
  var strings = chars.SelectMany(c => GenerateStrings(length - 1), (c, s) => c + s);
  foreach (var str in strings)
    yield return str;
}

调用GenerateStrings(3)将使用延迟评估生成长度为3的所有字符串(因此字符串不需要额外的存储空间)。

在生成字符串的IEnumerable之上构建您可以创建primites来缓冲和处理字符串的缓冲区。一个简单的解决方案是使用Reactive Extensions for .NET。这里你已经有一个Buffer原语:

  GenerateStrings(3)
    .ToObservable()
    .Buffer(10)
    .Subscribe(list => ... ship the list to another computer and process it ...);

Subscribe中的lambda将使用List<String>调用,最多10个字符串(调用Buffer时提供的参数)。

除非您拥有无数的计算机,否则您仍然需要从池中提取计算机,并且只有在计算完成后才将它们回收到池中。

从这个问题的评论中可以明显看出,即使您有多台计算机,也无法处理26 ^ 30个字符串。

答案 1 :(得分:-1)

我现在没有时间编写一些代码,但实际上如果你的RAM耗尽,则使用磁盘。我正在思考一个线程运行一个算法来找到组合,另一个线程将结果保存到磁盘并释放RAM。