How does recursion work here? - java

Recursion is a new practice for me and I am trying to get better at it and understand how the methods return. I have the following program but am unfailiar with how to use the this keyword. Can you please review the code and walk me through the program showing the values held by the variables as the methods execute?
I have tried numerous things to determine how the value answer in the compute method holds 14 after execution can anyone walk me through the first few recursive calls so I can try and figure out the rest?
public class Recurs1 {
public static void main (String [] arg) {
Recurs1 r = new Recurs1();
r.compute();
}
public void compute() {
int [] stuff = {1, 2, 3, 4};
int answer = this.go(stuff, 0);
System.out.println("The answer is " + answer);
}
private int go(int[] numbers, int spot) {
if (numbers.length == spot) return spot;
int value = this.go(numbers, spot + 1 );
return value + numbers[spot];
}
}

Ok so a few things I notice here:
The purpose of go() seems to be calculating the sum of the numbers in the array. If this is the case, your method should look like this:
private int go(int[] numbers, int spot) {
if (numbers.length - 1 == spot) return numbers[spot];
int value = this.go(numbers, spot + 1 );
return value + numbers[spot];
}
This is because numbers.length in this case will return 4, but the last element in this array is at index 3 (arrays are 0-indexed).
This way, when the function is called with the second parameter set to 3, it will return the value of the last element in the array and then the code will "bubble up" (as I like to call it) and calculate the sum of the elements by subsequently returning the current summed value + the value of the current call.
As for your problem with the this keyword, it's actually very simple. this always refers to the current class instance your code is in. In this case, you create a Recurs1 instance called r in your main function so whenever you call a method on that particular object, the this keyword used in those methods will refer to r. If you created multiple Recurs1 objects (each with potential different internal states) in your program, their respective this references would always point to themselves allowing you to access their member variables and methods.
Hope that helps and good luck, recursion is usually what most people have trouble getting their heads around at first but once you get used to it it's pretty cool!

OK so this is not an answer to your question per se, more like a lesson in recursion.
Keep in mind I have never tried to to do this with a java class.
Recursion means a function that calls itself repeatedly until a answer has been reached, or your function detects you are running out of stack space.
You first step into the function determines if you will call yourself.
When you call yourself you will push a new copy of the data onto the stack and begin executing. I think in the case of java you will allocate a new object into the heap ( don't quote me on this ) and each invocation will have a new set of variables that get populated with new values.
As you recurse deeper and deeper you simply allocate new copies of the object until you find the answer or run out of memory.
If you find the answer you then return the result to the previous level in the stack of objects eg:
int foo(int i ){
if(some condition){
return foo(i);
} else
return i
}
as You can see if the condition tests true the foo() keeps getting called. Now at each call, the variables of foo() are saved for as many levels deep as you go. If the condition tests false then each instance of foo() returns to the previous until you are at the original invocation of foo() which then returns to the caller of foo().
Clear as Mud?

Related

Recursive Knapsack returning wrong answer

The following code should be returning 16 as far as I can tell but for some reason, it returns 10. Does anyone know what my bug might be? Basically it's the Knapsack problem in Java and I've ran through the whole code on paper and it seems to return the right answer to me but I cannot figure out why when it's properly run, it returns back 10.
Any help would be much appreciated. Thanks!
import java.util.Stack;
public class knapsackProblem
{
public static int optimalValue(Stack<item> items, int totalWeight)
{
if (items.isEmpty())
return 0;
int value = items.peek().value;
int weight = items.peek().weight;
items.pop();
if (totalWeight<weight)
return optimalValue(items, totalWeight);
return Math.max(optimalValue(items,totalWeight), value + optimalValue(items, totalWeight-weight));
}
public static void main(String args[])
{
int knapsackWeight = 15;
Stack<item> items = new Stack<item>();
items.push(new item(7,10));
items.push(new item(3,6));
System.out.println(optimalValue(items, knapsackWeight));
}
}
class item
{
public int weight;
public int value;
public item(int aWeight, int aValue)
{
weight = aWeight;
value = aValue;
}
}
Your Stack is being modified across the calls. So a line like
return Math.max(optimalValue(items,totalWeight), value + optimalValue(items, totalWeight-weight));
will have two different copies of items for each call. Not what you want.
Instead of using Stack, try changing things around to use an ArrayList. Then pass your index of which item you're evaluating into the optimalValue method instead. This should help you work through the items correctly.
I haven't gone through the whole algorithm, but an obvious problem is that every time you call optimalValue on a Stack, it will pop one or more items from the stack. But a Stack, and the items in the stack, are objects, which means they're passed around by reference. So in this line:
return Math.max(optimalValue(items,totalWeight), value + optimalValue(items, totalWeight-weight));
This calls optimalValue twice. The first time you call it with items as a parameter, optimalValue will pop one or more elements from items. Then the statement calls optimalValue again with items as a parameter--and this will NOT use the same items stack that you passed to the first optimalValue call, but it will use the items with the already-popped-off items still popped off (from the first call). I really doubt this is what you want. If you do things this way, then at some point I think you'll have to make a copy of your Stack. Or you'll need to rethink things and do it a different way (maybe you can use an array or ArrayList, so that the items aren't actually popped off but you could pass a "starting index" from one optimalValue call to the recursive call).
I don't know whether there are other problems with your solution in addition to this one.

How to adding two method returns together

Ok, So I have a method
public static int getTotalLegCountDog (ArrayList<Dog> dogList)
{
int temp = 0;
for (int i = 0; i < dogList.size(); i++)
{
temp = dogList.get(i).getNumLegs();
totalLegsDogs += temp;
}
return totalLegsDogs;
}
It adds up the total legs of dogs and returns them as totalLegsDogs and there is another that totals the legs for cats.
Now I'd like a method that would take both the returned totalLegsDogs and returned totalLegsCats and add them together. My try is below (It returns 0), any help would be great!
public int getTotalLegCount ()
{
totalLegs = totalLegsDogs + totalLegsCats;
return totalLegs;
}
Was not calling the Method correctly. The math in the Problem was solid. The problem was the Method output call.
As far as I can tell, there's nothing wrong with the methods themselves - likely you're calling getTotalLegCount before actually counting the legs.
Fix 1 (preferred): Have getTotalLegCount call the methods.
public int getTotalLegCount (ArrayList<Dog> dogList, ArrayList<Cat> catList) {
totalLegs = getTotalLegCountDog(dogList) + getTotalLegCountCat;
return totalLegs;
}
Fix 2: Make it very clear that the leg-counting methods are to be called first. This is the inferior solution, as it requires more effort on the future programmer's part (and that might be future-you!).
I don't think you've shown us enough of your code to do any troubleshooting. It looks like you must have a global static count for dog legs and cat legs? I can't figure out your use case, but any rate, you need to make sure both your counting methods are called before you do anything with the member variables or else they will not be initialized. Example:
DogCatCounter.getTotalLegDogCount(...);
DogCatCounter.getTotalLegCatCount(...);
new DogCatCounter().getTotalLegCount();
The result from that third line should be correct as long as no other instances of DogCatCounter have modified your static variables. In other words, if you have multiple instances of DogCatCounter, any calls to your counting methods are going to modify your global static members.

Java Stack Comparison

I'm wondering how to accomplish this:
Compare two Stack objects
Do this recursively
After the method that
does this is complete, the Stacks remain as they were to begin with
(i.e. same order, same items).
Only the push, pop and isEmpty methods for Stack is available.
I'm looking more for theoretical help than coding help, but any insight would be appreciated.
Two stacks are identical if their top level elements are identical, and the remaining stacks are identical (namely, the recursive condition).
Now, think what to do just before returning from the method call, in order to leave the stacks the same way they where given at the invocation time.
---EDIT---
The working Java code (derived from Markus A. solution, but with an interesting use of "finally" and with generics):
static <T> boolean compareStacks(Stack<T> a, Stack<T> b) {
if (a.isEmpty() != b.isEmpty()) return false;
if (a.isEmpty() && b.isEmpty()) return true;
T element_a = a.pop();
T element_b = b.pop();
try {
if (((element_a==null) && (element_b!=null)) || (!element_a.equals(element_b)))
return false;
return compareStacks(a, b);
} finally { // restore elements
a.push(element_a);
b.push(element_b);
}
}
In pseudo-code, you could do something like this:
boolean compareStacks(a, b) {
if (a.isEmpty() != b.isEmpty()) return false; // check if one is empty
if (a.isEmpty() && b.isEmpty()) return true; // check if both are empty
element_a = a.pop(); // grab elements and compare them
element_b = b.pop();
if (((element_a==null) && (element_b!=null)) || !element_a.equals(element_b)) {
a.push(element_a); // if they are not equal, restore them and return false
b.push(element_b);
return false;
}
result = compareStacks(a, b); // compare shortened stacks recursively
a.push(element_a); // restore elements
b.push(element_b);
return result; // return result from recursive call
}
With recursion it always helps to think of it as 2 parts, a "Setup" and a recursive function. Your setup would create the proper situation (create the two stacks, pass them in, etc) and then calls the recursive method and when the recursive method is done, report the results.
In your case you probably want this signature for the "recursive" method:
public boolean compareStacks(Stack one, Stack two)
If that method pops & compares the top tow elements of the stack, it can return false right then (saying they don't compare). If they do, you now have two stacks, each one shorter than before. You already know how to compare those two stacks, right (You just wrote the method to do so!).
at the end you can "Push" your one element back onto each stack to restore it's previous state before returning.
There will be a little trickiness in restoring the stack in the case where they don't compare, and ensuring that if the compareStack you call fails it properly passes that up to the previous state, even if the "current" compareStack succeeds, but those are implementation details--just thought I'd mention those so you don't overlook them.
There is a cute solution with Try/finally (no catch, return from within the try and push back onto the stack in the finally) that would make the code pretty slick, but it's easy enough without it.

Null pointer exception in server

This is a client-server programm.
For each client server has a method, which checks if there are some messages to this client.
Code:
while (bool) {
for(int j = 0;j<Start.bases.size();j++){
if(Start.bases.get(j).getId() == id){
if(!Start.bases.get(j).ifEmpty()){
String output = Start.bases.get(j).getMessage();
os.println(output);
System.out.println(output +" *FOT* "+ addr.getHostName());
}
}
}
Each thread has an id.
So everything seems to be OK, but I get strange null pointer Exception at this line
if(Start.bases.get(j).getId() == id){
id - integer.
It is really strange, because I have run in debug this part and checked that "bases" and "id" are not null and bases have apropriate fields.
bases is not empty.
By the way bases is static(because every thread can use it) and bases is declared before this method is used.
This line doesn't cause problems
for(int j = 0;j<Start.bases.size();j++){
May it is because of method getId() ?
public int getId(){
return id;
}
What is the problem?
Edited.
static ArrayList<Base> bases;
bases = new ArrayList<Base>();
Class Base:
public class Base {
private ServerThread st;
private int id;
private String name;
private ArrayList<String> messages;
public Base(String n, ServerThread s_t, int i_d){
messages = new ArrayList<String>();
st = s_t;
name = n;
id = i_d;
}
public String getName(){
return name;
}
public int getId(){
return id;
}
public ServerThread getThr(){
return st;
}
public String getMessage(){
String ret = "";
if(!messages.isEmpty()){
ret = messages.get(0);
messages.remove(messages.get(0));
}
return ret;
}
public void addMessage(String m){
messages.add(m);
}
public boolean ifEmpty(){
return messages.isEmpty();
}
}
Thanks.
In this line of code:
(Start.bases.get(j).getId() == id
you may have such exception in such cases:
1) bases is null - you said its wrong
2) bases.get(j) - it may occur only if you collection size was reduced during iteration(as mentioned Gray)
3) Start.bases.get(j).getId() is null. But as you mentioned getId() method return primitive int, so its not the case as in this situation you receive null ponter while casting - in line " return id;".
So you should check second case.
Given this:
"I have run in debug this part and checked that "bases" and "id" are not null and bases have apropriate fields"
and this:
bases is static(because every thread can use it)
I think it's pretty likely that you have a race condition. In a race condition, there are two threads simultaneously accessing the same data structure (in this case, Start.bases). Most of the time, one thread's code completes faster, and everything goes the way you expect them to, but occasionally the other thread gets a head-start or goes a little faster than usual and things go "boom".
When you introduce a debugger with a break point, you pretty much guarantee that the code with the break point will execute last, because you've stopped it mid-execution while all your other threads are still going.
I'd suggest that the size of your list is probably changing as you execute. When a user leaves, is their entry removed from the "base" list? Is there some other circumstance where the list can be changed from another thread during execution?
The first thing I'll suggest is that you switch your code to use iterators rather than straight "for" loops. It won't make the problem go away (it might actually make it more visible), but it will make what's happening a lot clearer. You'll get a ConcurrentModificationException at the point where the modification happens, rather than the less helpful NullPointerException only when a certain combination of changes happens.):
for(Base currentBase : Start.bases)
{
if(currentBase.getId() == id && !currentBase.ifEmpty())
{
String output = currentBase.getMessage();
os.println(output);
System.out.println(output +" *FOT* "+ addr.getHostName());
}
}
If you do get a concurrent modification exception with the above code, then you're definitely dealing with a race condition. That means that you'll have to synchronize your code.
There are a couple of ways to do this, depending on how your application is structured.
Assuming that the race is only between this bit of code and one other (the part doing the removing-from-the-list), you can probably solve this scenario by wrapping both chunks of code in
synchronized(Start.bases)
{
[your for-loop/item removal code goes here]
}
This will acquire a lock on the list itself, so that those two pieces of code will not attempt to update the same list at the same time in different threads. (Note that it won't stop concurrent modification to the Base objects themselves, but I doubt that's the problem in this case).
All of that said, any time you have a variable which is read/write accessed by multiple threads it really should be synchronized. That's a fairly complicated job. It's better to keep the synchronization inside the object you're managing if you can. That way you can see all the synchronization code in one place, making you less likely to accidentally create deadlocks. (In your code above, you'd need to make the "for" loop a method inside your Start class, along with anything else which uses that list, then make "bases" private so that the rest of the application must use those methods).
Without seeing all the other places in your code where this list is accessed, I can't say exactly what changes you should make, but hopefully that's enough to get you started. Remember that multi-threading in Java requires a very delicate hand!

poset iteration implementation correctness

I wrote a custom iterator class that iterates over the set of numbers found in a PoSet, and here is my code:
private class IntGenerator implements Iterator {
private Iterator<Integer> i;
private Set<Integer> returnedNumbers;
public IntGenerator () {
returnedNumbers = new HashSet<Integer> ();
i = S.iterator();
}
public boolean hasNext() {
return i.hasNext();
}
public Object next() {
int n = i.next();
for (Pair p : R) {
if (isInSecondElmPair(p, n)) {
if (returnedNumbers.contains(p.getFirstElm())) {
returnedNumbers.add(n);
return n;
}else{
returnedNumbers.add(p.getFirstElm());
return p.getFirstElm();
}
}else if (isInFirstElmPair(p, n)){
returnedNumbers.add(n);
return n;
}
}
return n;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
The thing is that when returning a number, I should abide by the partial order rules, that is:
1. if (x, y) belongs to R, then x should be returned before y
However the code above seems to follow that ordering but it is creating duplicates, how can I fix my code to not allow it?
NOTE: In my code, S is the set of numbers in the PoSet, it is a HashSet and R is an arraylist of pairs (pair: a class i created that takes 2 ints as param) to hold the relations in the PoSet.
Is there any way to fix this problem?
Thanks
Your next method always calls i.next(), and returns one of two things:
the value that i.next() returned
some value that is less than that value.
This means that if your poset contains {1,2,3,4} and uses the natural ordering for integers, and i.next() returns 4, then either you return 4 now (due to 1, 2, and 3 already having been returned), or you will never return 4 (because it's not less than any future value).
The reason you're getting duplicates is that you return one value for every value of i.next(), and there are some values that never get returned (see previous paragraph), so naturally there are some values that get returned multiple times in compensation. Note that you never check whether the value returned from i.next() has previously been returned by your next() method, so if an element in the poset is not greater than any other element, then when i.next() returns that element, your next() method will automatically return it, even if it has previously returned it.
I think the only sensible fix for this to completely change your approach; I don't think your current approach can readily be made to work. I think your iterator's constructor needs to copy all the elements of the poset into an acceptably-ordered list, and then the next() method will simply return the next element of that list. Or, alternatively, since your current approach already requires iterating over R on every call to next() anyway, it might make more sense to base your iterator on an iterator over R. (I'm assuming here that R is already ordered using itself; if it's not, then your for loop makes no sense at all, and will essentially return randomly selected elements.)
If you do want to try to stick with your approach, then you'll need to keep track not only of the elements that your next() method has returned, but also of the elements that i.next() returned but that your next() method did not return; you'll need to be able to return these elements later.
Also, your for (Pair p : R) loop doesn't do what you want — it automatically returns n as soon as it finds any element that is less than n that's already been returned, even if there are other elements less than n that haven't been returned yet. (This is if R is already ordered using itself. If it isn't, then this loop has even bigger problems.)

Categories

Resources