What is the output of this code using a stack? - java

We're learning stacks in Intermediate Programming and we're using Practice-IT! for coding examples. I'm stuck on this one question:
"Write a method splitStack that takes a stack of integers as a parameter and splits it into negatives and non-negatives. The numbers in the stack should be rearranged so that all the negatives appear on the bottom of the stack and all the non-negatives appear on the top. In other words, if after this method is called you were to pop numbers off the stack, you would first get all the nonnegative numbers and then get all the negative numbers. It does not matter what order the numbers appear in as long as all the negatives appear lower in the stack than all the non-negatives. You may use a single queue as auxiliary storage."I tried writing some code for it but it's saying it's wrong. I don't know where I went wrong since I'm learning this for the first time.
public Stack<Integer> splitStack(Stack<Integer> intSt)
{
Stack posSt = new Stack();
Stack negSt = new Stack();
for(int i = 0; i<intSt.size(); i++)
{
intSt.pop();
if (intSt.peek() < 0)
{
negSt.push(intSt);
}
else
{
posSt.push(intSt);
}
}
for(int i = 0; i<negSt.size(); i++)
{
negSt.pop();
intSt.push();
}
for(int i=0; i<posSt.size(); i++)
{
posSt.pop();
intSt.push();
}
return intSt;
}

There are multiple issues with the code so I'm gonna tackle them one by one but first, I'm gonna talk about the root of them: you need to develop your code on an IDE that supports intellisense and debugging, for java, the one I like the most is IntelliJ.
With a good IDE, you'd have seem that:
pop() has a return value, so when you pop, you should store the popped value like int poppedValue = intSt.pop();
push requires a value, so if you want to push the value you just popped from intSt you should go with negSt.push(poppedValue); (you push poppedValue, not the intSt)
after fixing all your pushes and pops, the program would still give wrong results because intSt.size() changes as you pop the stack, so your for would exit before the stack was empty and thus, would not split the whole stack, you could fix this by changing your fors into whiles as in while(intSt.size() > 0)
The last one would be the hardest one to catch, so I'm gonna suggest you some homework that will help you start finding all those issues by yourself:
Download an actual java IDE (IntelliJ, Eclipse or Netbeans).
Understand those tools intellisense (all of them bring up a context menu when you hit period '.' after a variable name, that menu contains a lot of information about methods and properties of the variable)
Learn to set up a breakpoint.
Learn step-over, step-into and step-out.
Learn how to use the "watch" window.
After that, will never want to work directly on a site anymore, you'll always develop on an IDE and then copy your work somewhere else after it's done, it really saves you a lot of time.

Related

Why are these statements equal? Stack methods in java

Why are the following statements equivalent? emptyRow and emptyCol are Integer stacks, and Grid is a two dimensional array of integers. There is no need for you to know what the program does, but in case you're wondering it's a sudoku puzzle solving algorithm that uses basic back-tracking.
Both statements allow the program to run without any bugs, but I don't understand how this is possible since .pop() returns the top most integer in the first implementation, while the second one first pops the top most items and retrieves the integers directly under those.
Statement A:
Grid[emptyRow.pop()][emptyCol.pop()] = 0;
Statement B:
emptyRow.pop();
emptyCol.pop();
Grid[emptyRow.peek()][emptyCol.peek()] = 0;
Sorry if this is a silly logic problem with my code, I'm just checking to see if there is something I don't know about how stack operations work.
Statement A is the same as
Grid[emptyRow.peek()][emptyCol.peek()] = 0;
emptyRow.pop();
emptyCol.pop();
I think you have the order confused, and perhaps in your use case it doesn't matter but the code is not the same.

Value (not index) greater than 3 in array causes java.lang.ArrayIndexOutOfBoundsException

I'm a novice programmer. This may be a simple problem but I've never seen this before. First of all, let me clarify that I'm not even trying to manipulate the index. Here's the part of the code that is causing the exception:
int[] bumpercatcher = new int[4];
//time variable that helps control events
int time = 0;
public void setup()
{
bumpercatcher[0]=4;
bumpercatcher[1]=4;
bumpercatcher[2]=4;
bumpercatcher[3]=4;
As you can see I'm trying to set them all equal to 4 at the start of the program. This causes the arrayindexoutofbounds exception. If I set them all equal to 0~3 then there is no problem (until I set them to a value greater than 3 later in the program). I don't understand it.
-it doesn't matter if I set the array size to 10, I still get the same exception
-it doesn't matter if I set only one of the values (i.e. at index 1, which is definitely within bounds of the array). same exception
Is there something I'm doing wrong? Thanks.
well, here' the entire code if you want to take a look(not too long, 1 class, bad programming practies): http://dl.dropbox.com/u/33501308/Pong.java
Here's the html from which you can see the program from (not much to see. it just freezes instantly.): http://dl.dropbox.com/u/33501308/bin.zip
by the way I'm using eclipse.
I don't really know what SSCEE is. sorry
Your posted code file includes loops along the lines of
for(int j: bumpercatcher) {
if(bumpercatcher[j]>5)
...
}
This is an issue. This is a different kind of loop than a traditional for loop. It is an extended or enhanced for, also called a foreach. It reads "for each integer j in array bumpercatcher do x." You are taking your element j (a value) and using it as an index to the array. When your value exceeds the maximum index, you will get an exception.
Write your code with a proper for loop if you want to access by index, or try simply restructuring your logic like
for (int j : bumpercatcher) {
if (j > 5) // j is the value!
...
}
I'm not sure what the problem is, but a far more readable way of doing this would be with a for loop:
for(int i = 0; i < bumpercatcher.length; i++) {
bumpercatcher[i] = 4;
}

How do you (get around) dynamically naming variables?

I'm not sure if I'm using the right nomenclature, so I'll try to make my question as specific as possible. That said, I imagine this problem comes up all the time, and there are probably several different ways to deal with it.
Let's say I have an array (vector) called main of 1000 random years between 1980 and 2000 and that I want to make 20 separate arrays (vectors) out of it. These arrays would be named array1980, array1981, etc., would also have length 1000 but would contain 1s where the index in the name was equal to the corresponding element in main and 0s elsewhere. In other words:
for(int i=0; i<1000; i++){
if(main[i]==1980){
array1980[i]=1;
} else {
array1980[i]=0;
}
Of course, I don't want to have to write twenty of these, so it'd be good if I could create new variable names inside a loop. The problem is that you can't generally assign variable names to expressions with operators, e.g.,
String("array"+ j)=... # returns an error
I'm currently using Matlab the most, but I can also do a little in Java, c++ and python, and I'm trying to get an idea for how people go about solving this problem in general. Ideally, I'd like to be able to manipulate the individual variables (or sub-arrays) in some way that the year remains in the variable name (or array index) to reduce the chance for error and to make things easier to deal with in general.
I'd appreciate any help.
boolean main[][] = new boolean[1000][20];
for (int i=0; i < 1000; i++) {
array[i][main[i]-1980] = true;
}
In many cases a map will be a good solution, but here you could use a 2-dim array of booleans, since the size is known before (0-20) and continuous, and numerable.
Some languages will initialize an array of booleans to false for every element, so you would just need to set the values to true, to which main[i] points.
since main[i] returns numbers from 1980 to 2000, 1980-main[i] will return 1980-1980=0 to 2000-1980=20. To find your values, you have to add 1980 to the second index, of course.
The general solution to this is to not create variables with dynamic names, but to instead create a map. Exactly how that's done will vary by language.
For Java, it's worth looking at the map section of the Sun collections tutorial for a start.
Don Roby's answer is correct, but i would like to complete it.
You can use maps for this purpose, and it would look something like this:
Map<Integer,ArrayList<Integer>> yearMap = new HashMap<Integer,ArrayList<Integer>>();
yearMap.put(1980,new ArrayList<Integer>());
for (int i = 0; i < 1000; i++){
yearMap.get(1980).add(0);
}
yearMap.get(1980).set(999,1);
System.out.println(yearMap.get(1980).get(999));
But there is probably a better way to solve the problem that you have. You should not ask how to use X to solve Y, but how to solve Y.
So, what is it, that you are trying to solve?

Stack Overflow Error java

I'm trying to solve a problem that calls for recursive backtracking and my solution produces a stackoverflow error. I understand that this error often indicates a bad termination condition, but my ternimation condition appears correct. Is there anything other than a bad termination condition that would be likely to cause a stackoverflow error? How can I figure out what the problem is?
EDIT: sorry tried to post the code but its too ugly..
As #irreputable says, even if your code has a correct termination condition, it could be that the problem is simply too big for the stack (so that the stack is exhausted before the condition is reached). There is also a third possibility: that your recursion has entered into a loop. For example, in a depth-first search through a graph, if you forget to mark nodes as visited, you'll end up going in circles, revisiting nodes that you have already seen.
How can you determine which of these three situations you are in? Try to make a way to describe the "location" of each recursive call (this will typically involve the function parameters). For instance, if you are writing a graph algorithm where a function calls itself on neighbouring nodes, then the node name or node index is a good description of where the recursive function is. In the top of the recursive function, you can print the description, and then you'll see what the function does, and perhaps you can tell whether it does the right thing or not, or whether it goes in circles. You can also store the descriptions in a HashMap in order to detect whether you have entered a circle.
Instead of using recursion, you could always have a loop which uses a stack. E.g. instead of (pseudo-code):
function sum(n){
if n == 0, return 0
return n + sum(n-1)
}
Use:
function sum(n){
Stack stack
while(n > 0){
stack.push(n)
n--
}
localSum = 0
while(stack not empty){
localSum += stack.pop()
}
return localSum
}
In a nutshell, simulate recursion by saving the state in a local stack.
You can use the -Xss option to give your stack more memory if your problem is too large to fix in the default stack limit size.
As the other fellas already mentioned, there might be few reasons for that:
Your code has problem by nature or in the logic of the recursion. It has to be a stoping condition, base case or termination point for any recursive function.
Your memory is too small to keep the number of recursive calls into the stack. Big Fibonacci numbers might be good example here. Just FYI Fibonacci is as follows (sometimes starts at zero):
1,1,2,3,5,8,13,...
Fn = Fn-1 + Fn-2
F0 = 1, F1 = 1, n>=2
If your code is correct, then the stack is simply too small for your problem. We don't have real Turing machines.
There are two common coding errors that could cause your program to get into an infinite loop (and therefore cause a stack overflow):
Bad termination condition
Bad recursion call
Example:
public static int factorial( int n ){
if( n < n ) // Bad termination condition
return 1;
else
return n*factorial(n+1); // Bad recursion call
}
Otherwise, your program could just be functioning properly and the stack is too small.

Java Binary search

Trying to perform a binary search on a sorted array of Book objects.
Its not working well, it returns the correct results for some of the objects, but not all.
I went through the loop on paper and it seems that a number can get missed out due to rounding #.5 upwards.
Any ideas how to make this work?
Book found = null;
/*
* Search at the center of the collection. If the reference is less than that,
* search in the upper half of the collection, else, search in the lower half.
* Loop until found else return null.
*/
int top = numberOfBooks()-1;
int bottom = 0;
int middle;
while (bottom <= top && found == null){
middle = (bottom + top)/2;
if (givenRef.compareTo(bookCollection.get(middle).getReference()) == 0) {
found = bookCollection.get(middle);
} else if (givenRef.compareTo(bookCollection.get(middle).getReference()) < 0){
bottom = middle + 1;
} else if (givenRef.compareTo(bookCollection.get(middle).getReference()) > 0){
top = middle - 1;
}
}
return found;
A couple suggestions for you:
there's no need to keep a Book variable. In your loop, just return the book when it's found, and at the end return null. And you can also remove the boolean check for the variable in the while condition.
the middle variable can be scoped inside the loop, no need to have it live longer.
you're doing bookCollection.get(middle).getReference() three times. Consider creating a variable and then using it.
the middle = (bottom + top)/2 is a classic mistake in binary search implementation algorithms. Even Joshua Bloch, who wrote the Java Collection classes, made that error (see this interesting blog post about it). Instead, use (bottom+top) >>> 1, to avoid integer overflow for very large values (you probably wouldn't encounter this error, but it's for the principle).
As for your actual problem statement, rounding would be downwards (integer division), not upwards. To troubleshoot the problem:
are you sure the numberOfBooks() method corresponds to the length of your collection?
are you sure the compareTo() method works as expected for the types you are using (in your code example we do not know what the getReference() return type is)
are you sure your collection is properly sorted according to getReference()?
and finally, are you sure that using givenRef.compareTo(bookCollection.get(middle).getReference()) < 0 is correct? In standard binary search implementations it would be reversed, e.g. bookCollection.get(middle).getReference().compareTo(givenRef) < 0. This might be what donroby mentions, not sure.
In any case, the way to find the error would be to try out different values and see for which the output is correct and for which it isn't, and thus infer what the problem is. You can also use your debugger to help you step through the algorithm, rather than using pencil and paper if you have to run many tests. Even better, as donroby said, write a unit test.
What about Collections.binarySearch()?
All of JRL's suggestions are right, but the actual fail is that your compares are reversed.
I didn't see this immediately myself, but replicating your code into a function (using strings instead of Books), writing a some simple Junit tests and then running them in the debugger made it really obvious.
Write unit tests!
I found the problem.
It turns out i was binary searching my bookCollection arrayList, and NOT the new sroted array i had created - sortedLib.
Silly mistake at my end, but thanks for the input and suggestions!

Categories