C#:蛮力与模式

时间:2016-05-23 13:38:50

标签: c# brute-force

我想知道是否有人可以帮助我。我正在尝试使用一种遵循特定模式的强力算法。 我可以使用一些草率的代码输出模式,但这些东西对我来说是一种新的东西。我真的不知道怎么从这里开始。如果你知道我怎么能做到这一点,我真的很赞成它。

模式看起来像这样

  

AA0AA0A0

所以我希望它从 AA0AA0A0 AA9AA9A9 强制执行,然后转到 AA0AA0B0

我非常感谢所有的建议。我试图谷歌一些解决方案,但没有真正找到任何特别的。

流程说明: 从生成第一个字符串AA0AA0A0开始。 然后它一直生成到AA0AA0A9。 然后它从下一个数字开始,因此它将是AA0AA1A0。 因此它将一直计入AA9AA9AA9,这将导致它跳转到AA0AA0B0。

还更新了代码,以便它现在正在运行。

private static char[] fCharList = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
    private static char[] fNumList = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

    static void Main(string[] args)
    {
        StartBruteForce(8);
    }

    public static void StartBruteForce(int length)
    {
        StringBuilder sb = new StringBuilder(length);
        char currentChar = fCharList[0];
        char currentNum = fNumList[0];

        for (int i = 1; i <= 2; i++)
        {
            sb.Append(currentChar);
        }
        for (int i = 1; i <= 1; i++)
        {
            sb.Append(currentNum);
        }
        for (int i = 1; i <= 2; i++)
        {
            sb.Append(currentChar);
        }
        for (int i = 1; i <= 1; i++)
        {
            sb.Append(currentNum);
        }
        for (int i = 1; i <= 2; i++)
        {
            sb.Append(currentChar);
        }
        for (int i = 2; i <= 1; i++)
        {
            sb.Append(currentNum);
        }
        //Console.WriteLine(sb);
        //Console.ReadLine();

        ChangeCharacters(7, sb, length);
    }

    private static StringBuilder ChangeCharacters(int pos, StringBuilder sb, int length)
    {
        for (int i = 0; i <= sb.Length - 1; i++)
        {
            //sb.setCharAt(pos, fCharList[i]);

            sb.Replace(sb[pos], fNumList[i], pos, 1);
            //sb.Replace(sb[pos], fCharList[i], pos, 1);

            if (pos == length - 1)
            {
                // Write the Brute Force generated word.
                Console.WriteLine(sb.ToString());
                Console.ReadLine();
            }
            else
            {
                ChangeCharacters(pos - 1, sb, length);
            }
        }

        return sb;
    }

7 个答案:

答案 0 :(得分:1)

首先阅读我关于如何计算笛卡尔积的文章:

https://blogs.msdn.microsoft.com/ericlippert/2010/06/28/computing-a-cartesian-product-with-linq/

现在应该清楚如何继续:

var results = from product in CartesianProduct(
              new[] { charList, charList, charList, charList, charList, numList, numList, numList } )
              let a = product.ToArray()
              select "" + a[0] + a[1] + a[5] + a[2] + a[3] + a[6] + a[4] + a[7];

看看LINQ的力量:在一个声明中解决你的组合问题。

答案 1 :(得分:1)

另一种替代解决方案:

var results = from a0 in charList
              from a1 in charList
              from a2 in charList
              from a3 in charList
              from a4 in charList
              from a5 in numList
              from a6 in numList
              from a7 in numList
              select "" + a0 + a1 + a5 + a2 + a3 + a6 + a4 + a7;

再次,感谢LINQ。

,这是一个很好的单语句解决方案

答案 2 :(得分:0)

我认为如果你有一个返回下一个“模式”字符串的函数会更好,所以你可以有一个for循环。

这样的事情:

public static string Next(string pattern)
{
    bool carry = true;
    var sb = new List<char>();
    int t;
    for(int i = pattern.Length - 1; i >= 0; i--)
    {
        if (!carry)
        {
            sb.Insert(0, pattern[i]);
            continue;
        }
        if (char.IsDigit(pattern[i]))
        {
            t = int.Parse(pattern[i].ToString()) + 1;
            if (t == 10)
            {
                sb.Insert(0, '0');
                carry = true;
            }
            else
            {
                sb.Insert(0, t.ToString()[0]);
                carry = false;
            }
        }
        else
        {
            t = (int)pattern[i] + 1;
            if (t == 91)
            {
                sb.Insert(0, 'A');
                carry = true;
            }
            else
            {
                sb.Insert(0, Convert.ToChar(t));
                carry = false;
            }
        }
    }
    return new string(sb.ToArray());
}

检查.Net Fiddle

答案 3 :(得分:0)

一些简单的循环将迭代并每次构建一个新的字符串。你可以将字符转换为int和back。所以你可以将每个字母视为一个数字。假设您的模式始终为AA0AA0A0。如果这种情况发生了变化,则需要使程序更加智能化。

this.googleMap = googleMap;

答案 4 :(得分:0)

我认为最简单的方法是将模式分成两部分;一个用于数字,一个用于字符。数字从000升级到999,字符从AAAAA升级到ZZZZZ。然后你只需要将数字拼接到字符的正确位置。

IEnumerable<string> Strings()
{
    var digits = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    var chars = Enumerable.Range((int)'A', (int)'Z' - (int)'A' + 1).Select(i => (char)i).ToArray();
    for (var c = 0L; c < Math.Pow(chars.Length, 5); ++c)
    {
        var cstr = chars[(c / (chars.Length * chars.Length * chars.Length * chars.Length) % chars.Length)].ToString()
                 + chars[(c / (chars.Length * chars.Length * chars.Length) % chars.Length)]
                 + chars[(c / (chars.Length * chars.Length) % chars.Length)]
                 + chars[(c / (chars.Length) % chars.Length)]
                 + chars[(c % chars.Length)];

        for (var i = 0L; i < 999; ++i)
        {
            var istr = (i / 100 % 10).ToString()
                     + (i / 10 % 10).ToString()
                     + (i % 10).ToString();

            var str = cstr.Substring(0, 2) + istr.Substring(0, 1) + cstr.Substring(2, 2) + istr.Substring(1, 1) + cstr.Substring(4, 1) + istr.Substring(2, 1);
            yield return str;
        }
    }
}

使用它就像这样:

var early = Strings().Take(15);
var late = Strings().Skip(1234).Take(15);
foreach (var s in early.Concat(late))
{
    Console.WriteLine(s);
}

将打印出来:

AA0AA0A0
AA0AA0A1
AA0AA0A2
AA0AA0A3
AA0AA0A4
AA0AA0A5
AA0AA0A6
AA0AA0A7
AA0AA0A8
AA0AA0A9
AA0AA1A0
AA0AA1A1
AA0AA1A2
AA0AA1A3
AA0AA1A4
AA2AA3B5
AA2AA3B6
AA2AA3B7
AA2AA3B8
AA2AA3B9
AA2AA4B0
AA2AA4B1
AA2AA4B2
AA2AA4B3
AA2AA4B4
AA2AA4B5
AA2AA4B6
AA2AA4B7
AA2AA4B8
AA2AA4B9

答案 5 :(得分:0)

public static IEnumerable<String> loop()
{
    char[] chars = new char[] { 'a', 'b', 'c' };
    for (int i = 0; i < 3000; i++)
    {
        string s = string.Format("aa{0}aa{1}{2}{3}", (i % 1000) / 100, (i % 100) / 10, chars[(i % 10000) / 1000], i % 10);
        System.Diagnostics.Debug.WriteLine(s);
        yield s;
    }
}

答案 6 :(得分:0)

替代解决方案:

  • 制作一个从0到10 * 10 * 10 * 26 * 26 * 26 * 26 * 26 - 1的计数器。它应该很长。

  • 在计数器的每个刻度线上,将数字设为c。底部数字是'0' + c%10。下一个数字是'0' + c/10%10。接下来是'0' + c/(10*10)%10。底部字母为'A' + c/(10*10*10)%26。下一个字母是'A' + c/(10*10*10*26)%26。等等。

  • 按正确的顺序将字母和数字放在一起并得出结果。

将其转换为代码留作练习。