Backtracking bruteforce Java password cracker - java

I have this homework assignment to make a recursive method to crack a password of a given length, n (unlimited and unknown!) made of small English letters, a-z ONLY.
Here's the class "Password" that creates a random password:
import java.util.Random;
public class Password {
private String _password = "";
public Password(int length) {
Random generator = new Random();
for (int i = 0; i < length; ++i) {
this._password = this._password + (char) (generator.nextInt(26) + 97);
}
}
public boolean isPassword(String st) {
return st.equals(this._password);
}
public String getPassword() {
return this._password;
}
}
And here is the question in detail:
"You must write a static recursive method,
public static String findPassword(Password p, int length) that "cracks" the code.
Here's an example of a main method:
public class Main {
public static void main(String[] args) {
Password p = new Password(5);
System.out.println(p.getPassword());
System.out.println(Ex14.findPassword(p, 5));
}
}
Important notes:
The method MUST be recursive, without using ANY loops.
You may not use the getPassword method.
If you would like to use a method of the String class, you may only use the following: charAt, substring, equals, length.
You MAY use overloading, but you MAY NOT use other methods. (You cannot use String.replace/String.replaceall)
You MAY NOT use static(global) variables.
You MAY NOT use any Array. "
Here's what I have until now, which clearly doesn't work; :\
public static String findPassword(Password p, int length) {
return findPassword(p, length, "", 'a');
}
public static String findPassword(Password p, int length, String testPass, char charToChange) {
int currDig = testPass.length() - 1;
if (p.isPassword(testPass))
return testPass;
if (length == 0) // There is no password.
return ""; // Returns null and not 0 because 0 is a password.
if (length > testPass.length())
return findPassword(p, length, testPass + charToChange, charToChange);
if (testPass.length() == length) {
//TODO if charToChange is 'z', then make it the one before it '++', and reset everything else to a.
//if (charToChange == 'z') {
// charToChange = 'a';
// String newString = testPass.substring(0, currDig-1) +
// (charToChange++)
// +testPass.substring(currDig+1,testPass.length()-1);
System.out.println("it's z");
// TODO currDig --;
// String newerString = testPass.substring(0, currDig - 1)
// + (char) (testPass.charAt(testPass.length() - 1) - 25);
// currDig--;
}
return "";
}
Thank you very much! much appreciated!
- TripleS

Related

How do I increase numDigits without making the method non-static?

There's three pieces of the code I was given in my BigInteger homework that requires us to store, as the name suggests, integers of extreme size into linked lists, given a String input.
If given a string "0054321" the resulting linked list will store 1->2->3->4->5 in positional order, disregarding insignificant digits.
But as I try to traverse through the string, I am trying to increment numDigits by 1 each time I find a significant digit.
BigInteger.java (The code I'm working on right now)
package bigint;
import sun.security.x509.InvalidityDateExtension;
public class BigInteger {
boolean negative;
int numDigits;
DigitNode front;
public BigInteger() {
negative = false;
numDigits = 0;
front = null;
}
public static BigInteger parse(String integer)
throws IllegalArgumentException {
int a = 0;
int b = 0;
this.front = new DigitNode(1, null);
int length = integer.length();
while (length > 0 && a <= length) {
if (integer.charAt(a) == '-') {
this.negative = true;
a++;
}
if (integer.charAt(a) == ' ' && this.numDigits == 0) {
a++;
}
if (integer.charAt(a) == ' ' && this.numDigits == 0) {
a++;
continue;
}
if (Character.isDigit(integer.charAt(a))) {
if(integer.charAt(a) == ' ' && this.numDigits == 0) {
a++;
continue;
}
this.numDigits = this.numDigits + 1;
}
/* IMPLEMENT THIS METHOD */
}
// following line is a placeholder for compilation
return null;
}
DigitNode.java (The class that encapsulates the linked list, NOT ALLOWED TO EDIT THIS)
package bigint;
public class DigitNode {
int digit;
DigitNode next;
DigitNode(int digit, DigitNode next) {
this.digit = digit;
this.next = next;
}
public String toString() {
return digit + "";
}
}
BigTest.java (The tester class that tests whether the parse/add/multiply methods word, NOT ALLOWED TO EDIT THIS)
package bigint;
import java.io.IOException;
import java.util.Scanner;
public class BigTest {
static Scanner sc;
public static void parse()
throws IOException {
System.out.print("\tEnter integer => ");
String integer = sc.nextLine();
try {
BigInteger bigInteger = BigInteger.parse(integer);
System.out.println("\t\tValue = " + bigInteger);
} catch (IllegalArgumentException e) {
System.out.println("\t\tIncorrect Format");
}
}
public static void add()
throws IOException {
System.out.print("\tEnter first integer => ");
String integer = sc.nextLine();
BigInteger firstBigInteger = BigInteger.parse(integer);
System.out.print("\tEnter second integer => ");
integer = sc.nextLine();
BigInteger secondBigInteger = BigInteger.parse(integer);
BigInteger result = BigInteger.add(firstBigInteger,secondBigInteger);
System.out.println("\t\tSum: " + result);
}
public static void multiply()
throws IOException {
System.out.print("\tEnter first integer => ");
String integer = sc.nextLine();
BigInteger firstBigInteger = BigInteger.parse(integer);
System.out.print("\tEnter second integer => ");
integer = sc.nextLine();
BigInteger secondBigInteger = BigInteger.parse(integer);
BigInteger result = BigInteger.multiply(firstBigInteger,secondBigInteger);
System.out.println("\t\tProduct: " + result);
}
public static void main(String[] args)
throws IOException {
// TODO Auto-generated method stub
sc = new Scanner(System.in);
char choice;
while ((choice = getChoice()) != 'q') {
switch (choice) {
case 'p' : parse(); break;
case 'a' : add(); break;
case 'm' : multiply(); break;
default: System.out.println("Incorrect choice");
}
}
}
private static char getChoice() {
System.out.print("\n(p)arse, (a)dd, (m)ultiply, or (q)uit? => ");
String in = sc.nextLine();
char choice;
if (in == null || in.length() == 0) {
choice = ' ';
} else {
choice = in.toLowerCase().charAt(0);
}
return choice;
}
}
However, I get the errors of:
java: non-static variable this cannot be referenced from a static context,
For any this.numDigits or this.front or this.negative.
Whenever I try to increase numDigits, or change the value of the integer to positive, it happens. Somebody please help, Data Structures is really kicking my butt right now.
this refers to the instance that is calling a method. Static methods do not have an associated instance (generally shouldn't be called from an instance at all), and therefore there is no this instance.
However, you can create an instance inside of your static method and affect its fields, for example:
public static BigInteger parse(String integer)
throws IllegalArgumentException {
BigInteger parsedBI = new BigInteger();
//...
parsedBI.front = new DigitNode(1, null);
//...
parsedBI.numDigits = parsedBI.numDigits + 1;
//...
}
Also (I'm one to talk as an SO noob myself), avoid giving more code in your questions than is needed (minimal reproducible example).
public static BigInteger parse(String integer)
The parse method is defined as a static function, so it doesn't have access to any BigInteger instance. "this" is meaningless. No instance has been created yet.
You could create a new BigInteger instance inside of parse method. That object would then have access to its instance variables like numDigits.
bi = new BigInteger()
Then you can access bi.numDigits rather than this.numDigits which doesn't make sense. Here bi points to an object instance of BigInteger whereas this doesn't point to anything because we're not inside an instance, we're in a static method.
Think of the static parse method as just a helper function that in theory could've resided somewhere outside the class definition, but is inside the class definition for convenience and clarity. Its job is to create a BigInteger instance by parsing text.

Error in my Word program in Java

This is my code and it compiles fine but when I try to create a string it says
Error: cannot find symbol - variable racer
public class Word {
private String original;
public Word(String s) {
original = s;
}
public String reverse () {
String reverse= "";
int x = 1;
int length = original.length();
while (length - x >= 0) {
reverse = reverse + original.substring(length -x);
x++;
}
return reverse;
}
public boolean isPalindrome() {
if(original.equals(reverse()))
return true;
else
return false;
}
}
The stated problem is not in the code posted - my guess is irrelephant's comment is correct, ie change new Word(racer) --> new Word("racer").
But I offer this to eliminate any chance of any errors in your code by basically eliminating your code:
public class Word {
private String original;
public Word(String s) {
original = s;
}
public boolean isPalindrome()
return new StringBuilder(original).reverse().toString().equals(original);
}
}
or if you must expose a reverse() method:
public class Word {
private String original;
public Word(String s) {
original = s;
}
public String reverse () {
return new StringBuilder(original).reverse().toString();
}
public boolean isPalindrome()
return reverse().equals(original);
}
}
I don't see the variable racer anywhere, but since you're using reverse inside a method, I'd recommend making it
Most likely, racer was never defined
Either that or the method was called w/o quotes
isPalindrome(racer)//note the lack of quotes
change reverse() to this
private() String reverse () {
String reverse= "";
int x = 1;
int length = original.length();
while (length - x >= 0) {
reverse = reverse + original.substring(length -x);
x++;
}
return reverse;

how to use recursion for converting String to int

I want to convert String input into int using recursion. This is the code I came up with but if my input is 123456 it only returns 124. If I enter 1234567, it gives an error.
import java.util.*;
public class Problem1 {
static int x =0;
static int counter = 0;
//input
public static void main(String[] args) {
Scanner scan = new Scanner (System.in);
String s= scan.nextLine();
System.out.println(recursive(s));
}
//recursive method
public static int recursive(String s){
if(s.length()==1){
x=(x*10)+ Integer.parseInt(s.substring(0,1));
return x;
}
else{
x = (x*10)+Integer.parseInt(s.substring(0,1));
counter++;
return recursive(s.substring(counter,s.length()-1));
}
}
}
import java.util.Scanner;
public class Problem1 {
static int x = 0;
static int counter = 0;
// input
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String s = scan.nextLine();
System.out.println(recursive(s));
}
// recursive method
public static int recursive(String s) {
if (s.length() == 1) {
x = (x * 10) + Integer.parseInt(s.substring(0, 1));
return x;
} else {
x = (x * 10) + Integer.parseInt(s.substring(0, 1));
counter++;
return recursive(s.substring(1, s.length()));
}
}
}
Look at your static counter variable. You are incrementing it every time. But you only want to have the substring starting at 1 (so cut off the first "letter").
So instead of using:
counter++;
return recursive(s.substring(counter,s.length()-1));
consider using:
return recursive(s.substring(1)); // you even don't really need the length
Because the String s parameter is as follows:
1st call: 1234567
2nd call: 234567
3rd call: 34567
4th call: 4567
...
So, you only have to cut off the first letter.
Btw: your sample "project" is a really funny one ;)
A few notes to start:
If you're doing recursion, you probably don't want to use a member variable. It's not wrong to do so, but not really typical of the pattern (your x variable).
It's often handy to pass in state through the recursion, although you wouldn't have to (that is, current value of x).
Your case is a little odd because you have to change your current parse value for every sub-parse (shifting by 10 each time); makes it a little more complicated.
If you are going to keep x as a member variable (which does seem to make sense in this case), you don't need to return anything from recursive.
Can you really not just use Integer.parseInt()?
Code could be much more simple, something like:
void recursive (String s)
{
if (s.length() == 0) return 0;
x = x * 10 + Integer.parseInt(s.substring(0, 1));
recursive(s.substring(1));
}
recursion("1234567", 0, 1)
The above code will turn the string "1234567" into an int using recursion. You must pass the string you want to convert, and then 0 and 1.
public static int recursion(String s, int result, int place) {
result += place * Integer.parseInt(s.charAt(s.length() - 1) + "");
if(s.length() == 1) {
return result;
}
else {
return recursion(s.substring(0, s.length() - 1), result, place * 10);
}
}
public static int computeStr(String str) {
if (str.equals("")) {
return 0;
}
int x = 1;
for (int i = 0; i < str.length() - 1; i++) {
x = x * 10;
}
x = x * Integer.parseInt(str.substring(0, 1));
return x + computeStr(str.substring(1));
}
For example: "2432" is (2 * 1000) + (4 * 100) + (3*10) + (2*1) = 2432
this algorithm begins at first position (2) from 2432
I know its kind of a late response but you could try something like this :-
private static int stringToInt(String string) {
if (string.length() == 0) {
return 0;
}
int rv;
int num = string.charAt(string.length() - 1) - '0';
String restOfTheString = string.substring(0, string.length() - 1);
rv = stringToInt(restOfTheString) * 10 + num;
return rv;
}
Try something like this:
Subtracting the ASCII code of the '0' character from your character returns an integer:
public class StringRecursion {
static int counter = 0;
public static void main(String[] args) {
System.out.println(convertStringToInt("123456"));
}
public static int convertStringToInt(String input) {
if (input.length() == 1)
return input.charAt(0) - '0';
int value = convertStringToInt(input.substring(0, input.length() - 1));
counter++;
return value * 10 + input.charAt(counter) - '0';
}
}
Try it like this :
public static int conStrToInt(String str) {
if(str.length()==0)
{
return 0;
}
char cc = str.charAt(0);
String ros = str.substring(1);
int factor=1;
for(int i=0;i<str.length()-1;i++)
factor*=10;
factor=factor*(cc-'0');
return factor+conStrToInt(ros);
}

How to assign numbers to words in java?

I have a problem about the last part of the code. I want to assign numbers to specific words but i always get 0 value, even though I get those strings from the first System.out.println correctly, i cannot get the numerical equivalents of those strings at the second System.out.println.Any ideas how to solve this problem?
public static double number;
protected void myMethod(HttpServletRequest request, HttpServletResponse response) {
String speech= request.getParameter("speech");
System.out.println("The recognized speech is : "+ speech);
// There is no problem till here.
if(speech == "Hi")
number = 1 ;
if(speech== "Thanks")
number = 2 ;
if(speech== "Bye")
number = 0 ;
System.out.println("The number for the speech is : " + number);
}
However here i dont get the correct numbers but only 0 for each word!
The == will only be true if the Strings are the same object. Use:
if(speech.equals("Hi"))
or to match without case:
if(speech.equalsIgnoreCase("hi"))
You can't use the == operator to check if two Strings have the same value in Java, you need to use the .equals() or equalsIgnoreCase() methods instead:
if("Hi".equalsIgnoreCase(speech)) {
number = 1;
}
else if("Thanks".equalsIgnoreCase(speech)) {
number = 2;
}
else if("Bye".equalsIgnoreCase(speech)) {
number = 0;
}
else {
number = -1;
}
The reason for this is that the == operator compares references; that is it will return true if and only if the instance stored in variable speech is the same instance as the literal String you've created between double quotes ("Hi", "Thanks", or "Bye").
Note also that I use the equalsIgnoreCase() call on the literal String I'm declaring, rather than the variable that is assigned from the parameter. This way, if a speech == null, the method call is still valid ("Hi" will always be a String), and so you won't get a NullPointerException, and the flow will continue until the else branch.
Try the following snippet:
Main.java
public class Main {
public static void main(String[] args) {
List<StringWithValue> stringList = new ArrayList<StringWithValue>();
stringList.add(new StringWithValue("Hi", 1));
stringList.add(new StringWithValue("Thanks", 2));
stringList.add(new StringWithValue("Bye", 3));
String speech = "Hi";
int number = 0;
for(StringWithValue swv : stringList){
if(swv.getString().equals(speech)){
number = swv.getValue();
break;
} else {
number = -1;
}
System.out.println("The number for the speech is : " + number);
}
}
StringWithValue.java
public class StringWithValue {
private String string;
private int value;
public StringWithValue(String string, int value) {
this.string = string;
this.value = value;
}
public String getString() {
return string;
}
public int getValue() {
return value;
}
}
public static double number;
if(speech=="hi")
{
number=1;
}
else if(speech=="thanks")
{
number=2;
}
else if(speech=="Bye")
{
number=0;
}
else
{
System.out.println("Word Not Found");
}

how to uncompress a given string in java recursively?

this is very easy using iteration but i have to do this using recursion. I tried to keep a count of how many times a char occurs in a string, the position and the rest of the string and output.
public static String uncompress(String compressedText) {
return uncompress(compressedText, 1, 0, "");
}
public static String uncompress(String text, int count, int pos, String output) {
if (text.equals("")) {
return "";
}
if (Character.isLetter(text.charAt(pos))) {
output += text.charAt(0);
pos++;
}
else if(Character.isDigit(text.charAt(pos))) {
count = text.charAt(pos) - '0';
output += text.charAt(pos + 1);
count++;
pos++;
}
text = text.substring(pos + 1);
uncompress(text, count, pos, output);
return output;
}
There are multiple errors in your code such as:
you are substringing but also passing in a position, you should do one or the other
your base case is returning "" but instead it should return the accrued string 'output'
where you recurse you disregard the output from the returning method and just return the output in the current method so nothing is built up by the recursion
Below is code which uses only recursion both to parse the string and build up the output. I have added comments to show what is happening in the code. Note that, particularly in recursion, it is useful to have a printout of the current state so you can see what is happening at each stage so I have added this too.
Note that the getMultiple() method is in itself a very simple example of how recursion should work - that you call the same method but either A) pass in some work done in the current call so that it can be accrued by the base case or B) take the output of the method and add something to it / modify it before returning the modified output.
public class Recursion {
public static void main(String[] args) {
System.out.println(uncompress("10a2b"));
}
public static String uncompress(String compressedText) {
return uncompress(compressedText, "", "");
}
public static String getMultiple(char x, int N) {
if (N == 0) return "";
return ""+x+getMultiple(x,N-1);
}
public static String uncompress(String text, String count, String output) {
System.out.println("----");
System.out.println("TEXT:"+text);
System.out.println("COUNT:"+count);
System.out.println("OUTPUT:"+output);
if (text.equals("")) {
//base case - no text left to parse
return output;
}
if (Character.isLetter(text.charAt(0))) {
//letter case - need to take the count we have accrued, parse it into an integer and add to output
System.out.println(count);// * text.charAt(0);
output += getMultiple(text.charAt(0),Integer.parseInt(count));
count = "";
}
else if(Character.isDigit(text.charAt(0))) {
//digit case - need to add to the count but keep as a string because must be parsed later
count += (""+text.charAt(0));
}
//parse the *remainder* of the string, one character at a time, so pass in the substring(1)
return uncompress(text.substring(1), count, output);
}
}
Assuming that the input String has a correct format, try this:
public static String uncompress(String compressedText) {
if (compressedText.length() == 0)
return "";
return uncompress(compressedText, charToInt(compressedText, 0), 0);
}
public static String uncompress(String text, int count, int pos) {
if (pos == text.length() || (pos == text.length()-2 && count == 0))
return "";
else if (count == 0)
return uncompress(text, charToInt(text, pos+2), pos+2);
return text.charAt(pos+1) + uncompress(text, count-1, pos);
}
public static int charToInt(String str, int idx) {
return str.charAt(idx) - '0';
}

Categories