蛮力算法仅打印0

时间:2018-05-07 08:22:21

标签: c# brute-force

我正在C#上创建一个暴力算法(用于教育目的),我遇到了一个错误。

我的暴力方式就像一个时钟 - 字符串中的最后一个字符从程序开始时设置的字符数组中的0到最后一个字符上升,当它到达结尾时 - 重置为0并增加前一个字符由1等等。

然而,下面的代码仅打印0:

// Array with characters to use in Brute Force Algorithm.
    // You can remove or add more characters in this array.
    private static char[] fCharList =
    {
        '0','1','2','3','4','5','6','7','8','9','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','A','B','C','D','E','F','G','H','I','J','C','L','M','N','O','P',
                    'Q','R','S','T','U','V','X','Y','Z','~','!','@','#','$','%','^','&','*','(',')','[',']','{','}','.',',','/','?','\'','|','"',';',':','<','>','\\','=','-','+','`','_'
    };

    private static String password;

    static void Main(string[] args)
    {
        Console.WriteLine("Enter the password: ");
        password = Console.ReadLine();
        Bruteforce();
    }

    // The Bruteforce algorithm
    // Goes like a clock cycle: Last index goes from fCharList[0] to fCharList[fCharList.Length - 1] 
    // then resets and last index -1 increases and so on.

    public static String Bruteforce()
    {

        String currPass = fCharList[0].ToString();
        bool foundPass = false;

        for (int i = 1; !foundPass; i++)
        {
            // If there's a need to increase (foundd fCharList[fCharList.Length - 1] in the String)
            if (currPass.Contains(fCharList[fCharList.Length - 1]))
            {
                //If no need to increase the whole length and reset all the characters
                if (!(currPass.IndexOf(fCharList[fCharList.Length - 1]) == 0))
                {
                    String updateCurrPass = "";
                    for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
                    {
                        updateCurrPass += fCharList[0].ToString();
                    }
                    currPass.Insert(currPass.IndexOf(fCharList[fCharList.Length - 1]) - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt<char>(currPass.IndexOf(fCharList[fCharList.Length - 1]) - 1)) + 1].ToString() + updateCurrPass);
                }
            }
            else // If no cycle ended - continue increasing last "digit"
            {
                currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());
            }
            Console.Write(currPass + "  ");

        }
        return "";
    }

我尝试了currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());的所有问题(因为我怀疑打印过程本身可能会出现问题),但没有成功。

我还尝试使用断点和纸张跟踪代码,但仍然没有。 如果有人可以帮助我解决这个问题,那将是非常令人愉快的。

修改 以下,许多人建议updateCurrPass += fCharList[0].ToString();应该是updateCurrPass += fCharList[j].ToString();。我还没有检查过这个选项太深,但为了更好地解释我的情况,我希望它像时钟周期一样工作 - 当最后一个数字是fCharList中的最新字符时,前一个数字增加了等等。提到的代码重置已到达最后一个字符的数字。 (因此,如果字符串currPass是"0aa___"(_是最后一个字符),它将变为0ab000updateCurrPass添加3 0&#39; s,其余的该函数将a增加到b。

3 个答案:

答案 0 :(得分:1)

您是否认为因为您指定了updateCurrPass? :

for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
{
     updateCurrPass += fCharList[0].ToString();
}

我认为它应该涉及j或其他:

for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
{
     updateCurrPass += fCharList[j].ToString();
}

添加代码:

下面的代码什么也不做,因为函数会返回函数(而不是更改参数传递的对象),你应该添加currPass = currPass.Insert(...),如@Rafalon所述

else // If no cycle ended - continue increasing last "digit"
{
    currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());
}

请改用:

else // If no cycle ended - continue increasing last "digit"
{
    currPass = currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());
}

答案 1 :(得分:1)

@VincentElbertBudiman所述,您必须在循环中使用j而不是0。 (或者可能不是,我不确定我是否理解你的算法)

但还有更多内容:

您必须注意,在C#中,String是不可变的,这意味着currPass.Insert(...)本身不做任何事情,您必须重新分配结果currPass = currPass.Insert(...);

但是,嘿,我认为你的算法太复杂了。

我会做什么:

string currPass = fCharList[0].ToString();
bool found = false;
while(!found)
{
    currPass = IncreasePassword(currPass);
    found = CheckPass(currPass);
}

使用IncreasePassword

public static string IncreasePassword(string pass)
{
    bool changed = false;
    StringBuilder sb = new StringBuilder(pass);
    // loop through pass until we change something 
    // or we reach the end (what comes first)
    for(int i = 0; i < pass.Length && !changed; i++)
  //for(int i = pass.Length - 1; i >= 0 && !changed; i--)  
    {
        int index = Array.IndexOf(fCharList, sb[i]);
        // if current char can be increased
        if(index < fCharList.Length - 1)
        {
            // if we have __012 then we'll go on 00112
            // so here we replace the left __ with 00
            for(int j = i - 1; j >= 0 && sb[j] == fCharList[fCharList.Length - 1]; j--)
          //for(int j = i + 1; j < sb.Length && sb[j] == fCharList[fCharList.Length - 1]; j++)
            {
               sb[j] = fCharList[0];
            }
            // and here we increase the current char
            sb[i] = fCharList[index + 1];
            changed = true;
        }
    }
    // if we didn't change anything, it means every char were '_'
    // so we start with a fresh new full-of-0 string
    if(!changed)
    {
        return "".PadLeft(pass.Length + 1, fCharList[0]);
    }
    return sb.ToString();
}

Live example

<强>说明

这将通过以下方式从左到右工作:
假设我们fCharList{ '0','1','2' }进行简化 我们将:

0
1
2
00
10
20
01
11
21
02
12
22
000
100
200
010
110
210
020
....

测试结果

这是它提供的反向输入(因为我的解决方案相反)来自Weeble's suggestions

Input        Output
0            1
1            2
P            Q
_            00
00           10
_0           01
__CBA        00DBA
____         00000

请注意,fCharList 已损坏,因为C代替K

答案 2 :(得分:0)

虽然其他答案中指出了具体问题,但我是否可以建议您更广泛的问题是您是否试图立即做太多事情?您可能能够将整个算法编写成一个整体并进行调整直到它起作用,但这样做很难,并且很难确信它是正确的。你会发现更容易将算法分解为更小的函数并单独测试它们以确认它们能达到预期效果。

例如,您可以突破算法的一部分“给定我检查的最后一个密码,按顺序考虑的下一个密码是什么”?这是算法的核心,它可以与迭代所有可能的密码并根据当前密码进行测试的工作分开。它更容易测试!例如,您可以使用如下测试数据:

Input             Expected output
"0"               "1"
"1"               "2"
"P"               "Q"
"_"               "00"
"00"              "01"
"0_"              "10"
"ABC__"           "ABD00"
"____"            "00000"

当你发现你的功能没有给出部分或全部这些测试的正确答案时,你需要做一个更小,更具体的工作来弄清楚什么是错误的,而不是试图一次调试整个算法