Trouble with recursive method java - java

basically I have a brute force password guesser(I realize it's not very efficient) I have a process I want to make into a recursive method that i can pass a length integer and it will run with that amount of characters.
here is the code:
public static void generatePassword(int length)
{
// should be a recusive function learn how to do that
// 1 interval
for(int i =32;i<127;i++)// ascii table length
{
System.out.println((char)i);
}
// 2 interval
for(int z =32;z<127;z++)// ascii table length
{
for(int q =32;q<127;q++)// ascii table length
{
System.out.println((char)z+""+(char)q);
}
}
// 3 interval
for(int w =32;w<127;w++)// ascii table length
{
for(int o =32;o<127;o++)// ascii table length
{
for(int g =32;g<127;g++)// ascii table length
{
System.out.println((char)w+""+(char)o+""+(char)g);
}
}
}
}
the intervals return a string with that length example: 3rd interval will return every possible string combination with a length of 3. if anyone can help me automate this process and explain(i would like to learn rather then copy and paste) that would be great ! :)

A recursive method is a method that calls itself, it has a base-condition (also called stop condition) which prevents it from going into an infinite loop.
Lets take the first interval as an example:
for(int i = 32; i < 127; i++) { // ascii table length
System.out.println((char)i);
}
we can create a recursive method that'll do the same thing:
private void interval1(int i) {
if (i < 32 || i >= 127) return;
System.out.println((char)i);
interval1(i + 1);
}
in order to use it for our use-case, we should call this method with i=32: interval(32)
Hope this helps!

The function
Note that this will be EXTREMELY INEFFICIENT. This shouldn't ever be done in practice, since the number of String objects created is MIND-BOGGLINGLY HUGE (see bottom of answer)
public void recursivePrint(String prefix, int levels) {
if (levels <= 1) {
for (int i = 33; i < 127; ++i) {
System.out.println(prefix+(char)i);
}
} else {
for (int i = 33; i < 127; ++i) {
recursivePrint(prefix+(char)i, levels-1);
}
}
}
Then you call it with:
recursivePrint("", 5); // for printing all possible combinations of strings of length 5
The way it works
Each call to a function has it's own memory, and is stored seperately. When you first call the function, there is a String called prefix with a value of "", and an int called 'levels' which has a value of 5. Then, that function calls recursivePrint() with new values, so new memory is allocated, and the first call will wait until this new call has finished.
This new call has a String called prefix with a value of (char)34+"", and a levels with a value of 4. Note that these are completely separate instances of these variables to the first function call because remember: each function call has it's own memory (the first call is waiting for this one to finish). Now this second call makes another call to the recursivePrint() function, making more memory, and waiting until this new call finishes.
When we get to levels == 1, there is a prefix built up from previous calls, and all that remains is to use that prefix and print all the different combinations of that prefix with the last character changing.
Recursive methods are highly inefficient in general, and in this case especially.
Why you should never use it
This method is not just inefficient, though; it's infeasible for anything useful. Let's do a calculation: how many different possibilities are there for a string with 5 characters? Well there's 127-33=94 different characters you want to choose, then that means that you have 94 choices for each character. Then the total number of possibilities is 94^5 = 7.34*10^9 [that's not including the 5+ bytes to store each one] (to put that in perspective 4GB of RAM is around 4*10^9 bytes)

Here is your method implemented using recursion:
public static void generatePassword(int length, String s) {
if (length == 0) {
System.out.println(s);
return;
}
for (int i = 32; i < 127; i++) {
String tmp = s+((char) i);
generatePassword(length - 1, tmp);
}
}
All you have to do is to pass length and initial String (ie "") to it.
At if statement there is checked, if recursion should be stopped (when length of generated password is equals to expected).
At for-loop there is new character added to actual String and the method is invoked with shorter length and a new String as an argument.
Hope it helps.

Related

When to use for, while, or do-while loops/ How to start it

Started learning about loops and the different types today. My question is in this situation which type would i try to use? And what would be the advantage over the others? After looking over my lecture notes it seems that do-while should always be used but I'm certain that it is not the case.
Also how would I start that first one about returning a sum of the "given array." what is the given array? Is it just whatever I'm supposed to be plugging into the run arguments line?
public class SumMinMaxArgs {
// TODO - write your code below this comment.
// You will need to write three methods:
//
// 1.) A method named sumArray, which will return the sum
// of the given array. If the given array is empty,
// it should return a sum of 0.
//
// 2.) A method named minArray, which will return the
// smallest element in the given array. You may
// assume that the array contains at least one element.
// You may use your min method defined in lab 6, or
// Java's Math.min method.
//
// 3.) A method named maxArray, which will return the
// largest element in the given array. You may
// assume that the array contains at least one element.
// You may use your max method defined in lab 6, or
// Java's Math.max method.
//
// DO NOT MODIFY parseStrings!
public static int[] parseStrings(String[] strings) {
int[] retval = new int[strings.length];
for (int x = 0; x < strings.length; x++) {
retval[x] = Integer.parseInt(strings[x]);
}
return retval;
}
// DO NOT MODIFY main!
public static void main(String[] args) {
int[] ints = parseStrings(args);
System.out.println("Sum: " + sumArray(ints));
System.out.println("Min: " + minArray(ints));
System.out.println("Max: " + maxArray(ints));
}
}
All three forms have exactly the same expressive power. What you use in a certain situation depends on style, convention, and convenience. This is much like you can express the same meaning with different english sentences.
That said, do - while is mostly used when the loop should run at least once (i.e. the condition is checked only after the first iteration).
for is mostly used when you are iterating over some collection or index range.
The four kinds of loops supported in Java:
C-style for loop: for (int i = 0 ; i < list.size() ; ++i) { ... } when you want to access the index of some kind of list or array directly, or to do an operation multiple times.
foreach loop, when you want to iterate over a collection, but don't care about the index: for (Customer c : customers) { ... }
while loop: while (some_condition) { ... } when some code must executed as long as the condition is true. If the condition is false to start with, the code inside the block (i.e. inside the brackets) will never be executed.
do while loop: do { statement1; } while (condition); will execute statement1 even if the condition is false to begin with, but it will do so only once.

Not getting output for simple java program to find greatest prime factor

class LargestPrimeFactor{
public static void main(String args[]){
long p=0L;
long n=600851475143L;
for(long i=2L;i<(n/2);i++){
if((BigInteger.valueOf(i)).isProbablePrime(1)){
if(n%i==0){
p=i;
}
}
}
System.out.println(p);
}
}
It's problem 3 from Project Euler. I compiled it and no errors showed up. But am not getting any output. Whats the reason?
It is working (just add a print method inside the loop to check i for example).
You are currently using the Brute-Force method:
http://www.mathblog.dk/project-euler-problem-3/
If you visit the link the guy tells you an alternative solution for it.
The problem I see without having much knowledge about this is
that the operations you currently do are way too many.
You got the value "600851475143" stored in a long datatype and you try to
reach the half (300425737571,5) using the int i (counter in your for-loop).
https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#MAX_VALUE
This tells us: "A constant holding the maximum value an int can have,
2^(31)-1." = 2147483647
This is just 0,00715 (0,7%) of what you actually need.
So this leads us to an "Overflow".
Think of using the alternative method (first link)
and change the counter of your for-loop to type "long".
int maximum value is 2147483647 which is smaller than 600851475143/2
when index i reaches max value it will wrap around and start with negative number (-2147483648)
you should make your index i a long value
You have an infinite loop on the second for iteration you can only see it when you add logging before the end of the loop. It's not because it's not printing the value, when you stare at the console the iterator is still circling through 6857.
Try running the code with extra logging below.
public static void main(String args[]) {
int p = 0;
long n = 600851475143L;
for (int i = 2; i < (n / 2); i++) {
if ((BigInteger.valueOf(i)).isProbablePrime(1)) {
if (BigInteger.valueOf(n % i).compareTo(BigInteger.valueOf(0)) == 0) {
p = i;
System.out.println("Check == true Iteration"+p);
}
System.err.println("Second iterator"+p);
}
}
System.out.println("Final Value of P: "+p);
}
EDITED
The int data type can store values upto 2,147,483,647. To store numbers beyond that, use long.
long n = 600851475143L;
Not 600851475143 L, as that one space before L causes the system to not register it.
Also, int i in the for loop should be long i.

Java - Return random index of specific character in string

So given a string such as: 0100101, I want to return a random single index of one of the positions of a 1 (1, 5, 6).
So far I'm using:
protected int getRandomBirthIndex(String s) {
ArrayList<Integer> birthIndicies = new ArrayList<Integer>();
for (int i = 0; i < s.length(); i++) {
if ((s.charAt(i) == '1')) {
birthIndicies.add(i);
}
}
return birthIndicies.get(Randomizer.nextInt(birthIndicies.size()));
}
However, it's causing a bottle-neck on my code (45% of CPU time is in this method), as the strings are over 4000 characters long. Can anyone think of a more efficient way to do this?
If you're interested in a single index of one of the positions with 1, and assuming there is at least one 1 in your input, you can just do this:
String input = "0100101";
final int n=input.length();
Random generator = new Random();
char c=0;
int i=0;
do{
i = generator.nextInt(n);
c=input.charAt(i);
}while(c!='1');
System.out.println(i);
This solution is fast and does not consume much memory, for example when 1 and 0 are distributed uniformly. As highlighted by #paxdiablo it can perform poorly in some cases, for example when 1 are scarce.
You could use String.indexOf(int) to find each 1 (instead of iterating every character). I would also prefer to program to the List interface and to use the diamond operator <>. Something like,
private static Random rand = new Random();
protected int getRandomBirthIndex(String s) {
List<Integer> birthIndicies = new ArrayList<>();
int index = s.indexOf('1');
while (index > -1) {
birthIndicies.add(index);
index = s.indexOf('1', index + 1);
}
return birthIndicies.get(rand.nextInt(birthIndicies.size()));
}
Finally, if you need to do this many times, save the List as a field and re-use it (instead of calculating the indices every time). For example with memoization,
private static Random rand = new Random();
private static Map<String, List<Integer>> memo = new HashMap<>();
protected int getRandomBirthIndex(String s) {
List<Integer> birthIndicies;
if (!memo.containsKey(s)) {
birthIndicies = new ArrayList<>();
int index = s.indexOf('1');
while (index > -1) {
birthIndicies.add(index);
index = s.indexOf('1', index + 1);
}
memo.put(s, birthIndicies);
} else {
birthIndicies = memo.get(s);
}
return birthIndicies.get(rand.nextInt(birthIndicies.size()));
}
Well, one way would be to remove the creation of the list each time, by caching the list based on the string itself, assuming the strings are used more often than they're changed. If they're not, then caching methods won't help.
The caching method involves, rather than having just a string, have an object consisting of:
current string;
cached string; and
list based on the cached string.
You can provide a function to the clients to create such an object from a given string and it would set the string and the cached string to whatever was passed in, then calculate the list. Another function would be used to change the current string to something else.
The getRandomBirthIndex() function then receives this structure (rather than the string) and follows the rule set:
if the current and cached strings are different, set the cached string to be the same as the current string, then recalculate the list based on that.
in any case, return a random element from the list.
That way, if the list changes rarely, you avoid the expensive recalculation where it's not necessary.
In pseudo-code, something like this should suffice:
# Constructs fastie from string.
# Sets cached string to something other than
# that passed in (lazy list creation).
def fastie.constructor(string s):
me.current = s
me.cached = s + "!"
# Changes current string in fastie. No list update in
# case you change it again before needing an element.
def fastie.changeString(string s):
me.current = s
# Get a random index, will recalculate list first but
# only if necessary. Empty list returns index of -1.
def fastie.getRandomBirthIndex()
me.recalcListFromCached()
if me.list.size() == 0:
return -1
return me.list[random(me.list.size())]
# Recalculates the list from the current string.
# Done on an as-needed basis.
def fastie.recalcListFromCached():
if me.current != me.cached:
me.cached = me.current
me.list = empty
for idx = 0 to me.cached.length() - 1 inclusive:
if me.cached[idx] == '1':
me.list.append(idx)
You also have the option of speeding up the actual searching for the 1 character by, for example, useing indexOf() to locate them using the underlying Java libraries rather than checking each character individually in your own code (again, pseudo-code):
def fastie.recalcListFromCached():
if me.current != me.cached:
me.cached = me.current
me.list = empty
idx = me.cached.indexOf('1')
while idx != -1:
me.list.append(idx)
idx = me.cached.indexOf('1', idx + 1)
This method can be used even if you don't cache the values. It's likely to be faster using Java's probably-optimised string search code than doing it yourself.
However, you should keep in mind that your supposed problem of spending 45% of time in that code may not be an issue at all. It's not so much the proportion of time spent there as it is the absolute amount of time.
By that, I mean it probably makes no difference what percentage of the time being spent in that function if it finishes in 0.001 seconds (and you're not wanting to process thousands of strings per second). You should only really become concerned if the effects become noticeable to the user of your software somehow. Otherwise, optimisation is pretty much wasted effort.
You can even try this with best case complexity O(1) and in worst case it might go to O(n) or purely worst case can be infinity as it purely depends on Randomizer function that you are using.
private static Random rand = new Random();
protected int getRandomBirthIndex(String s) {
List<Integer> birthIndicies = new ArrayList<>();
int index = s.indexOf('1');
while (index > -1) {
birthIndicies.add(index);
index = s.indexOf('1', index + 1);
}
return birthIndicies.get(rand.nextInt(birthIndicies.size()));
}
If your Strings are very long and you're sure it contains a lot of 1s (or the String you're looking for), its probably faster to randomly "poke around" in the String until you find what you are looking for. So you save the time iterating the String:
String s = "0100101";
int index = ThreadLocalRandom.current().nextInt(s.length());
while(s.charAt(index) != '1') {
System.out.println("got not a 1, trying again");
index = ThreadLocalRandom.current().nextInt(s.length());
}
System.out.println("found: " + index + " - " + s.charAt(index));
I'm not sure about the statistics, but it rare cases might happen that this Solution take much longer that the iterating solution. On case is a long String with only a very few occurrences of the search string.
If the Source-String doesn't contain the search String at all, this code will run forever!
One possibility is to use a short-circuited Fisher-Yates style shuffle. Create an array of the indices and start shuffling it. As soon as the next shuffled element points to a one, return that index. If you find you've iterated through indices without finding a one, then this string contains only zeros so return -1.
If the length of the strings is always the same, the array indices can be static as shown below, and doesn't need reinitializing on new invocations. If not, you'll have to move the declaration of indices into the method and initialize it each time with the correct index set. The code below was written for strings of length 7, such as your example of 0100101.
// delete this and uncomment below if string lengths vary
private static int[] indices = { 0, 1, 2, 3, 4, 5, 6 };
protected int getRandomBirthIndex(String s) {
int tmp;
/*
* int[] indices = new int[s.length()];
* for (int i = 0; i < s.length(); ++i) indices[i] = i;
*/
for (int i = 0; i < s.length(); i++) {
int j = randomizer.nextInt(indices.length - i) + i;
if (j != i) { // swap to shuffle
tmp = indices[i];
indices[i] = indices[j];
indices[j] = tmp;
}
if ((s.charAt(indices[i]) == '1')) {
return indices[i];
}
}
return -1;
}
This approach terminates quickly if 1's are dense, guarantees termination after s.length() iterations even if there aren't any 1's, and the locations returned are uniform across the set of 1's.

2 dimensional array & method calls - beginner

I'm currently working on a homework assignment for a beginner-level class and I need help building a program that tests if a sodoku solution presented as an int[][] is valid. I do this by creating helper methods that check both rows, columns and grids.
To check the column I call a method called getColumn that returns a column[]. When I test it out it works fine. I then pass it out on a method called uniqueEntries that makes sure that there are no duplicates.
Problem is, when I call my getColumn method, it returns an array consisting of only one number (for example 11111111, 22222222, 33333333). I have no idea why it does that. Here is my code:
int[][] sodokuColumns = new int[length][length];
for(int k = 0 ; k < sodokuPuzzle.length ; k++) {
sodokuColumns[k] = getColumn(sodokuPuzzle, k);
}
for (int l = 0; l < sodokuPuzzle.length; l++) {
if(uniqueEntries(sodokuColumns[l]) == false) {
columnStatus = false;
}
}
my helper is as follows
public static int[] getColumn(int[][] intArray, int index) {
int[] column = new int[intArray.length];
for(int i = 0 ; i < intArray.length ; i++) {
column[i] = intArray[i][index];
}
return column;
}
Thanks !
You said:
when I call my getColumn method, it returns an array consisting of only one number (for example 11111111, 22222222, 33333333).
I don't see any issue with your getColumn method other than the fact it's not even needed because getColumn(sodokuPuzzle, k) is the same as sodokuPuzzle[k]. If you're going to conceptualize your 2D array in such a way that your first index is the column then for your purpose of checking uniqueness you only need to write a method to get rows.
The issue you're having would seem to be with another part of your code that you did not share. I suspect there's a bug in the logic that accepts user input and that it's populating the puzzle incorrectly.
Lastly a tip for checking uniqueness (if you're allowed to use it) would be to create a Set of some kind (e.g. HashSet) and add all of your items (in your case integers) to that set. If the set has the same size as your original array of items then the items are all unique, if the size differs there are duplicates.

Problem with recursive backtracking

Hey guys, recently posted up about a problem with my algorithm.
Finding the numbers from a set which give the minimum amount of waste
Ive amended the code slightly, so it now backtracks to an extent, however the output is still flawed. Ive debugged this considerablychecking all the variable values and cant seem to find out the issue.
Again advice as opposed to an outright solution would be of great help. I think there is only a couple of problems with my code, but i cant work out where.
//from previous post:
Basically a set is passed to this method below, and a length of a bar is also passed in. The solution should output the numbers from the set which give the minimum amount of waste if certain numbers from the set were removed from the bar length. So, bar length 10, set includes 6,1,4, so the solution is 6 and 4, and the wastage is 0. Im having some trouble with the conditions to backtrack though the set. Ive also tried to use a wastage "global" variable to help with the backtracking aspect but to no avail.
SetInt is a manually made set implementation, which can add, remove, check if the set is empty and return the minimum value from the set.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package recursivebacktracking;
/**
*
* #author User
*/
public class RecBack {
int WASTAGE = 10;
int BESTWASTAGE;
int BARLENGTH = 10;
public void work()
{
int[] nums = {6,1,2,5};
//Order Numbers
SetInt ORDERS = new SetInt(nums.length);
SetInt BESTSET = new SetInt(nums.length);
SetInt SOLUTION = new SetInt(nums.length);
//Set Declarration
for (int item : nums)ORDERS.add(item);
//Populate Set
SetInt result = tryCutting(ORDERS, SOLUTION, BARLENGTH, WASTAGE);
result.printNumbers();
}
public SetInt tryCutting(SetInt possibleOrders, SetInt solution, int lengthleft, int waste)
{
for (int i = 0; i < possibleOrders.numberInSet(); i++) // the repeat
{
int a = possibleOrders.min(); //select next candidate
System.out.println(a);
if (a <= lengthleft) //if accecptable
{
solution.add(a); //record candidate
lengthleft -= a;
WASTAGE = lengthleft;
possibleOrders.remove(a); //remove from original set
if (!possibleOrders.isEmpty()) //solution not complete
{
System.out.println("this time");
tryCutting(possibleOrders, solution, lengthleft, waste);//try recursive call
BESTWASTAGE = WASTAGE;
if ( BESTWASTAGE <= WASTAGE )//if not successfull
{
lengthleft += a;
solution.remove(a);
System.out.println("never happens");
}
} //solution not complete
}
} //for loop
return solution;
}
}
Instead of using backtracking, have you considered using a bitmask algorithm instead? I think it would make your algorithm much simpler.
Here's an outline of how you would do this:
Let N be number of elements in your set. So if the set is {6,1,2,5} then N would be 4. Let max_waste be the maximum waste we can eliminate (10 in your example).
int best = 0; // the best result so far
for (int mask = 1; mask <= (1<<N)-1; ++mask) {
// loop over each bit in the mask to see if it's set and add to the sum
int sm = 0;
for (int j = 0; j < N; ++j) {
if ( ((1<<j)&mask) != 0) {
// the bit is set, add this amount to the total
sm += your_set[j];
// possible optimization: if sm is greater than max waste, then break
// out of loop since there's no need to continue
}
}
// if sm <= max_waste, then see if this result produces a better one
// that our current best, and store accordingly
if (sm <= max_waste) {
best = max(max_waste - sm);
}
}
This algorithm is very similar to backtracking and has similar complexity, it just doesn't use recursion.
The bitmask basically is a binary representation where 1 indicates that we use the item in the set, and 0 means we don't. Since we are looping from 1 to (1<<N)-1, we are considering all possible subsets of the given items.
Note that running time of this algorithm increases very quickly as N gets larger, but with N <= around 20 it should be ok. The same limitation applies with backtracking, by the way. If you need faster performance, you'd need to consider another technique like dynamic programming.
For the backtracking, you just need to keep track of which element in the set you are on, and you either try to use the element or not use it. If you use it, you add it to your total, and if not, you proceeed to the next recursive call without increasing your total. Then, you decrement the total (if you incremented it), which is where the backtracking comes in.
It's very similar to the bitmask approach above, and I provided the bitmask solution to help give you a better understanding of how the backtracking algorithm would work.
EDIT
OK, I didn't realize you were required to use recursion.
Hint1
First, I think you can simplify your code considerably by just using a single recursive function and putting the logic in that function. There's no need to build all the sets ahead of time then process them (I'm not totally sure that's what you're doing but it seems that way from your code). You can just build the sets and then keep track of where you are in the set. When you get to the end of the set, see if your result is better.
Hint2
If you still need more hints, try to think of what your backtracking function should be doing. What are the terminating conditions? When we reach the terminating condition, what do we need to record (e.g. did we get a new best result, etc.)?
Hint3
Spoiler Alert
Below is a C++ implementation to give you some ideas, so stop reading here if you want to work on it some more by yourself.
int bestDiff = 999999999;
int N;
vector< int > cur_items;
int cur_tot = 0;
int items[] = {6,1,2,5};
vector< int > best_items;
int max_waste;
void go(int at) {
if (cur_tot > max_waste)
// we've exceeded max_waste, so no need to continue
return;
if (at == N) {
// we're at the end of the input, see if we got a better result and
// if so, record it
if (max_waste - cur_tot < bestDiff) {
bestDiff = max_waste - cur_tot;
best_items = cur_items;
}
return;
}
// use this item
cur_items.push_back(items[at]);
cur_tot += items[at];
go(at+1);
// here's the backtracking part
cur_tot -= items[at];
cur_items.pop_back();
// don't use this item
go(at+1);
}
int main() {
// 4 items in the set, so N is 4
N=4;
// maximum waste we can eliminiate is 10
max_waste = 10;
// call the backtracking algo
go(0);
// output the results
cout<<"bestDiff = "<<bestDiff<<endl;
cout<<"The items are:"<<endl;
for (int i = 0; i < best_items.size(); ++i) {
cout<<best_items[i]<<" ";
}
return 0;
}

Categories