我正在學習 java atm,我有點卡在當前的任務上,我的教練昨天給了我...
練習是:
- 創建一個 4 位密碼(就像字串變數一樣)。(允許使用 0-9 之間的數字和一個或多個這些特殊字符:'!'、'#'、'%')
- 通過嘗試所有可能性,找到一種暴力破解密碼的方法。
- 測量并輸出處理所花費的時間。
- 此外,輸出查找密碼所需的“嘗試”次數。
(我的教練說我應該盡可能少用方法,因為我現在還不知道如何撰寫方法或如何使用類等)
我設法讓它作業,但現在它需要大約 60 毫秒才能完成回圈。我的教練現在告訴我,我應該試著讓它處理得更快,這樣至少需要大約 20 毫秒。
我現在已經是什么讓我的代碼變慢了。這是因為我總是經歷所有可能性,將所有這些都添加到 ArreyList 中,然后我檢查 pw 是否與 ArreyList 中的這些可能性之一匹配。浪費時間。現在我的目標是像以前一樣經歷各種可能性,但只在找到密碼之前。之后,它應該停止回圈,以便它也停止添加其余不必要的組合。我試了又試,但現在我決定尋求幫助:)
那是我的代碼:
import java.util.ArrayList;
import java.util.Scanner;
public class trynew {
public static void main(String[] args) {
Scanner scn = new Scanner(System.in);
char[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '!', '%'};
System.out.println("\nPlease create 4 digit password. Allowed are numbers between 0-9 and following characters: #,!,%");
String passw = scn.nextLine();
ArrayList<String> check_it = new ArrayList<String>();
long start1 = System.currentTimeMillis();
for (int i = 0; i < digits.length; i ) {
for (int j = 0; j < digits.length; j ) {
for (int k = 0; k < digits.length; k ) {
for (int l = 0; l < digits.length; l ) {
check_it.add(digits[i] "" digits[j] "" digits[k] "" digits[l]);
}
}
}
}
long end1 = System.currentTimeMillis();
for (String sv : check_it) {
if (sv.equals(passw)) {
System.out.println("\nThe Password is: " sv);
System.out.println("It took " check_it.indexOf(sv) " tries, to find the password.");
}
}
System.out.println("Process time was " (end1 - start1) " milliseconds.");
}
}
My approach was to make the loop like that:
for (int i = 0; i < digits.length; i ) {
for (int j = 0; j < digits.length; j ) {
for (int k = 0; k < digits.length; k ) {
for (int l = 0; l < digits.length; l ) {
if (!(digits[i] "" digits[j] "" digits[k] "" digits[l]).equals(passw)){
check_it.add(digits[i] "" digits[j] "" digits[k] "" digits[l]);
}
}
}
}
}
然后我嘗試使用while回圈而不是if,我嘗試設定布林值等。我還設法讓它只添加組合,直到找到pw,但不知何故處理時間不會下降:/
The reason why I want to add the combos into check_it ArreyList is because otherwise, I wouldn't now how I get the numbers of tries it took, until pw is found...
Can someone help me please, or poke me at the right direction?! Thanks & Greets!
uj5u.com熱心網友回復:
這就是我想出的。
private static final char[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '!', '%'};
public static int guessPw(String pw) {
int attempts = 0;
char [] word = new char[pw.length()];
for (char a : digits) {
word[0] = a;
for (char b : digits) {
word[1] = b;
for (char c : digits) {
word[2] = c;
for (char d : digits) {
word[3] = d;
attempts ;
if (pw.equals(String.valueOf(word))) {
return attempts;
}
}
}
}
}
return -1;
}
public static void timeAttempt(String pw) {
long start = System.nanoTime();
int attempts = guessPw(pw);
System.out.println(String.format("It took %dms and %d attempts to guess '%s'", TimeUnit.MILLISECONDS.toSeconds(System.nanoTime() - start), attempts, pw));
}
public static void main(String[] args) {
timeAttempt("0000");
timeAttempt("%%%%");
}
uj5u.com熱心網友回復:
這段代碼應該可以作業。如果找到密碼,它只會打破每個回圈。
int tries = 0;
boolean found = false;
for (int i = 0; i < digits.length; i ) {
for (int j = 0; j < digits.length; j ) {
for (int k = 0; k < digits.length; k ) {
for (int l = 0; l < digits.length; l ) {
tries ;
if ((digits[i] "" digits[j] "" digits[k] "" digits[l]).equals(passw)) {
found = true;
break;
}
}
if (found)
break;
}
if (found)
break;
}
if (found)
break;
}
我不建議使用此代碼!這是相當粗略的。你為什么不把 for 回圈變成一個函式呢?找到密碼后,您可以從那里回傳嘗試。但我認為你可以自己解決這個問題:)
編輯:我會給你一個沒有功能的解決方案的提示。你覺得這個while回圈怎么樣?
while(!(digits[i] "" digits[j] "" digits[k] "" digits[l]).equals(passw))
在那里你只需要以正確的順序'增長' l、k、j 和 i :)
uj5u.com熱心網友回復:
與 Ryan 發布的內容非常相似。基本上你想避免創建一個字串。
在這里,我將輸入的密碼轉換為 char 陣列,并使用以下方法將輸入的密碼與生成的密碼進行比較Arrays.equals():
public static void main(String[] args) {
Scanner scn = new Scanner(System.in);
char[] digits = {'0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', '#', '!', '%'};
System.out.println("\nPlease create 4 digit password.");
System.out.println("Allowed are numbers between 0-9 and following characters: #,!,%");
System.out.print("Password: ");
String response = scn.nextLine();
char[] password = response.toCharArray();
long start1 = System.currentTimeMillis();
int counter = 0;
char[] pw = new char[4];
boolean foundIt = false;
for (int i = 0; i < digits.length && !foundIt; i ) {
pw[0] = digits[i];
for (int j = 0; j < digits.length && !foundIt; j ) {
pw[1] = digits[j];
for (int k = 0; k < digits.length && !foundIt; k ) {
pw[2] = digits[k];
for (int l = 0; l < digits.length && !foundIt; l ) {
counter ;
pw[3] = digits[l];
foundIt = Arrays.equals(pw, password);
}
}
}
}
long end1 = System.currentTimeMillis();
System.out.println("\nThe Password is: " response);
System.out.println("It took " counter " tries, to find the password.");
System.out.println("Process time was " (end1 - start1) " milliseconds.");
}
uj5u.com熱心網友回復:
其處理速度如此緩慢的原因是因為您的所有代碼都在單個執行緒中運行。您可以通過使蠻力代碼多執行緒來大大減少整體處理時間。
您的應用程式運行緩慢的另一個原因是它使用許多嵌套回圈來確定digits. 與其使用那些嵌套回圈,不如計算digits.
獲得所有可能排列的串列后,您可以使用 java 8parallelStream()并anyMatch()以多執行緒方式檢查哪個排列與密碼匹配。換句話說,計算機將能夠同時匹配 2 個或更多排列,pass 這將大大減少處理時間。下面是一個使用parallelStream()/的例子anyMatch()。
AtomicInteger threadSafeCounter = new AtomicInteger(); //Always use a thread safe integer when multiple threads will be manipulating it. This is to avoid race conditions.
char[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '!', '%'};
Scanner scn = new Scanner(System.in);
System.out.println("\nPlease create 4 digit password. Allowed are numbers between 0-9 and following characters: #,!,%");
String passw = scn.nextLine();
List<String> permutationList = new ArrayList(); //Calculate the 4-digit permutations from `digits` and add them to this list.
long start1 = System.currentTimeMillis();
permutationList.parallelStream().anyMatch(combination -> {
threadSafeCounter.incrementAndGet();
if(combination.equals(passw)){
System.out.println("\nthe password is " passw);
System.out.println("It took " threadSafeCounter.get() " tries, to find the password.");
return true;
}
else return false;
});
long end1 = System.currentTimeMillis();
System.out.println("Process time was " (end1 - start1) " milliseconds.");
digits您可以在此 SO 執行緒中找到有關如何從中生成排列的示例。如果您調整 Subash 在上述 SO 執行緒中發布的代碼,則排列生成代碼本身也可以成為多執行緒的。為此,您需要使用Fork/Join framework.
編輯:這是一篇很好的文章permutations,解釋了和之間的區別combinations。在我的示例中我計算排列而不是組合的原因是因為在這種情況下順序/排列很重要。
uj5u.com熱心網友回復:
這是相當有效的。
- 檢查是否存在特殊字符。如果是,則回傳 -1。
- 它將 4 位數字轉換為 int。
- 然后只需從 0 迭代到 9999 并與目標進行比較
- 它回傳嘗試次數,如果無效則回傳 -1
String [] data = { "9999", "9999%" };
for (String pwd : data) {
long start = System.nanoTime();
int tries = check(pwd);
long time = (long)(((System.nanoTime() - start)/1e9)*1000);
System.out.printf("Took %d tries in %d ms to validate `%s`%n", tries, time, pwd);
印刷
Took 10000 tries in 3 ms to validate `9999`
Took -1 tries in 0 ms to validate `9999%`
檢查方法
public static int check(String pwd) {
if (pwd.replaceAll("[!%#]", "").equals(pwd)) {
int pass = Integer.parseInt(pwd);
for (int i = 0; i < 10_000; i ) {
if (i == pass) {
return i 1;
}
}
}
return -1;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/447072.html
標籤:java for-loop arraylist nested-loops brute-force
