递归 - 破解随机生成的密码

问题描述

所以我已经找到了破解生成的 5 位密码所需的尝试次数,但是它使用 while 循环而不是递归来完成。我减少了字母的数量只是为了让它运行得更快并测试代码。我需要进行哪些更改才能使用递归而不是 for/while 循环破解密码?到目前为止,这是我的全部代码

//imports
import java.util.Scanner;
import java.util.Random;

class Main {
public static Random rr = new Random();

public static void main(String[] args) {
    // Letters for the random generated password
    // Variables
    String letters = "abcdefghijklmnopqrstuvwxyz1234567890";
    int PASSWORD = letters.length();
    // While statement to allow user to keep generating passwords
    while (true) {
        String password = "";
        Scanner input = new Scanner(system.in);
        // Print menu and uses 1 to generate password
        System.out.println("Press 1 to generate a random password");
        // Takes user input
        int UserOption = input.nextInt();
        // If user input equals 1
        if (UserOption == 1) {
            // Generate a 5-character passwords from the letters in the String
            //Print text is outside the loop to prevent it from printing it more than once in one try
            System.out.println("Your password is: ");
            for (int i = 0; i < 5; i++) {
                password = password + letters.charat(rr.nextInt(PASSWORD));
            }
            //To print the password and the number of attempts it took
            System.out.println(password);
            passCracking(password,letters,"");
        }
        // If user input is anything except 1
        else if (UserOption != 1) {
            // Print error
            System.out.println("Error");
        }
    }
}
// Method that creates random 5 digit strings and checks if it matches with the password
//Password Generator
private static String comparePass(String characters) {
    String comparePass = "";
    for (int i = 0; i < 5; i++) {
        comparePass = comparePass + characters.charat(rr.nextInt(characters.length()));
    }
    return comparePass;
}
//Recursive Method 
private static int passCracking(String password,String characters,int tries,String check) {
    //Base Case
    //If the password matches then return 0 to let the loop kNow we found the match and ends cracking the password
    if (check.equals(password)) {
        return 0;
    }
    //After checking it once,it checks again but if it doesn't match return -1 and does backtrack and calls upon the method again with different password combination
    else if (!check.equals("")) {
        if (!check.equals(password)) {
            return-1;
        }
    }
    //While loop where it keeps looping when its not the correct password
    while (true) {
        check = comparePass(characters);
        if (passCracking(password,characters,tries++,check) == 0) {
            //Print statement for number of attempts
            System.out.println("It took " + tries + " tries to crack the password");
            //Returns zero
            return 0;
        }
        //Add one to the attempt counter for every attempt in cracking the password
        tries++;
    }
}
}

解决方法

这是一个(主要是)递归解决方案,它检查给定 charset 中的每个字符排列,直到密码 maxPwdLength 的某个最大长度。您仍然可以使用额外的递归层替换 for 循环。

public class Main {

    public static void main(String... args) {
        String charset = "abcdefghijklmnopqrstuvwxyz1234567890";
        String pwd = crackPassword("",5,charset);
        System.out.println(pwd);
    }

    public static boolean checkPassword(String guess) {
        String ACTUAL_PASSWORD = "pwd01";  // Whatever the actual password is
        return guess.equals(ACTUAL_PASSWORD);
    }

    public static String crackPassword(String currentGuess,int maxPwdLength,String charset) {
        if (checkPassword(currentGuess)) {
            return currentGuess;  // This means we cracked the password
        }
        if (currentGuess.length() == maxPwdLength) {
            return null;
        }
        
        for (int i = 0; i < charset.length(); i++) {
            String nextGuess = currentGuess + charset.charAt(i);
            String result = crackPassword(nextGuess,maxPwdLength,charset);
            if (result != null) {
                return result;
            }
        }
        return null; 
    }
}

这里有一个更大的问题是你真的想对这个问题使用递归吗?递归可以带来一些优雅的解决方案,但函数调用不是免费的,因此使用递归进行大量调用会损害性能。在这种情况下,迭代解决方案可能会更高效。