Why does this while loop run after the condition is met? - java

When I do a regular while loop like this
int x = 0;
while (x < 2) {
System.out.println(x);
x = x + 1;
}
it prints
0
1
but this second while loop runs one more time after the condition is met.
class Hobbits {
String name;
public static void main(String [] args) {
Hobbits [] which = new Hobbits[3];
int number = -1;
while (number < 2) {
number = number + 1;
which[number] = new Hobbits();
which[number].name = "bilbo";
if (number == 1) {
which[number].name = "frodo";
}
if (number == 2) {
which[number].name = "sam";
}
System.out.print(which[number].name + " is a ");
System.out.println("good Hobbit name");
}
}
}
so the result is
bilbo is a good Hobbit name
frodo is a good Hobbit name
sam is a good Hobbit name
shouldn't it stop printing at "frodo is a good Hobbit name"
I set the condition for x < 2 so how does "sam" print if the while loop was supposed to stop at x == 1?
Edit: ohhh I get it now lol I was thinking like the increment was at the end of the code and the start was 0

Here's your test case more closely matching your code:
class Test {
public static void main(String[] args) {
int x = -1;
while (x < 2) {
x = x + 1;
System.out.println(x);
}
}
}
It does indeed print:
$ java Test
0
1
2
Your loop is not designed to stop when number is 2, it's designed to stop before the next iteration if the number is 2. Since you increment number early on in the loop, it will continue with that value until it's time to choose whether to iterate again.
Before the first iteration, number = -1 which is <2 so it should iterate.
Before the second iteration, number = 0, which is <2 so iterate.
Before the third iteration, number = 1, which is <2 so iterate.
Before the fourh iteration, number = 2, which is NOT <2 so stop.
You therefore get 3 iterations.
Your original test case had the right idea -- it's better to increment as the last step in the loop. That way, you start at 0 instead of -1, and you stop the loop based on the new value rather than the previous value.

I will try to trace through it for you.
First case this is what happens.
x = 0
is 0 < 2? yes
print 0
0 <- 0 + 1 // here it becomes 1
is 1 < 2? yes
print 1
1 <- 1 + 1 // here it becomes 2
is 2 < 2? no
exit program
second loop works a bit more like this
number = -1
is number < 2? yes
number <- -1 + 1 // here it becomes 0
make hobbit "bilbo" at index 0
0 does not equal either 1 or 2
print hobbit at index 0 who is "bilbo"
is 0 < 2? yes
0 <- 0 + 1 // here it becomes 1
number equals 1 so make "frodo" at index 1
print hobbit at index 1 who is "frodo"
is 1 < 2? yes
1 <- 1 + 1 // becomes 2
number equals 2 so make "sam" at index 2
print hobbit at index 2 who is "sam"
is 2 < 2? no
end program

There's nothing wrong in that behaviour. You set number = -1 and then you do a loop that will iterate while number < 2. So, -1, 0 and 1. Three iterations. What's the problem? Let's do a simple trace:
number = -1
(-1 < 2)? Yes. Execute code inside while.
number = number + 1 (0)
(0 < 2)? Yes. Execute code inside while.
number = number + 1 (1)
(1 < 2)? Yes. Execute code inside while.
number = number + 1 (2)
(2 < 2)? No. Continue with the next instruction after the while block.

you can solve this easily with replace
int number = -1;
to
int number = 0;
Because! -1 + 1 = 0;

Because you have 3 iterations that are true:
-1 < 2 == true
0 < 2 == true
1 < 2 == true
2 < 2 == false
Cheers

Related

Having problems understanding following simple algorithm

public class Test1
{
public static void main (String[]args)
{
int number = 0;
for (int i = 0; i < 5; i++)
{
if (number != 0)
{
number = i * number;
}
else
{
number = i;
}
}
System.out.println (number);
}
}
I'm not quite sure how this algorithm works. My thought process is:
We set number to 0 by default.
In the for loop we are just saying, continue counting i till it's no longer smaller than 5.
We say that if number isn't 0, we update number by multiplying it with i. So in our case, i is 0,1,2,3 and 4.
Else we are saying the number is i and i is what we were counting.
Lastly, we print number.
Am I missing something? Am I wrong somewhere?
If I run this code why do I get 24 as output? I cannot understand how this simple program works.
public class Test
{
public static void main (String[]args)
{
int number = 0;
for (int i = 0; i < 5; i++)
{
if (number != 0)
{
number = i * number;//For i=2, 3, 4
}
else
{
number = i;//This is executed twice - for i=0 and i=1
}
}
System.out.println (number);
}
}
Let's understand this program.
Execution begins from the main() method.
A variable named number is defined and initialized to 0.
A loop control variable named i is defined. Its initial value is 0 and it is increased by 1 at the end of every iteration till it reaches 5. Note that i is never modified inside the loop body.
For i = 0, the condition number != 0 is false, the else block is executed. number = i. The value of number remains 0.
For i = 1, the condition number != 0 is false, the else block is executed. number = i. The value of number changes to 1.
For i = 2, the condition number != 0 is true, the if block is executed. number = i * number. The value of number changes to 2.
For i = 3, the condition number != 0 is true, the if block is executed. number = i * number. The value of number changes to 6.
For i = 4, the condition number != 0 is true, the if block is executed. number = i * number. The value of number changes to 24.
Since i = 5, the loop breaks. The value of number is printed.
This is how we end up getting 24 as the output.
Executing the algorithm step by step will help understanding it.
Let's start with the first line. As you said, this line just sets number to 0.
int number = 0; | number: 0
I included the value of the variable on the right side after the bar.
Second step is to start with the loop. Before the loop starts, the counter variable i is set to zero.
int i = 0; | number: 0, i: 0
As a second step we have to check if the loop criterion is fulfilled, so that the body of the loop will be executed.
The criterion of the loop is i < 5 and since the current value of i is 0 and 0 < 5, the body of the loop is executed:
if (number != 0) {
number = i * number;
} else {
number = i;
}
Since it is an if statement, we have to see if the if-condition is fulfilled. number is currently 0, so number != 0 is not true. This means we go to the else branch with is:
number = i; | i = 0 -> number = 0
Since i is zero, number continues to be zero after this statement was executed.
This is the end of the first execution of the loop. Last thing the loop does before restarting is incrementing the counter:
i++; | number = 0, i = 1
Now i < 5 is still true, so the loop body runs again.
We still have number = 0 therefore number != 0 is still false.
Note that i was updated to 1, but number was not until now. Now:
number = i; | i = 1 -> number = 1
Now the loop increments the counter and starts anew:
i++; | i = 2
Still i < 5, so the body of the loop is executed again.
For the first time number != 0 is true, because number = 1.
So now we execute:
number = i * number; | i = 2 -> number = 2
number used to be 1, i is to, so i * number = 2
Again the loop body ends, the counter is incremented and the loop restarts, since 3 < 5:
i++; | i = 3
Here again number != 0, so we execute
number = i * number;
which yields number = 6 since 2 * 3 = 6.
The same process continues one more time with i = 4.
Now number = 4 * 6 = 24.
We increment the counter
i++; | i = 5, number = 24
Now i < 5 is no longer true, the loop exits and
System.out.println(number);
prints the current value of number, 24 to the screen.
Your thought process was good, but it wasn't exact or detailed enough because the meshing/merging of the sequence of the multiplication (of number) with the sequence of incrementing i is important.
Work it out on paper with a table, one column per variable, one line per instruction executed:
i number
null 0 int number = 0; // i has not been initialized yet.
0 0 int i = 0;
0 0 number = i; // it took the else branch
1 0 i++
1 1 number = i;
2 1 i++
2 2 number = i * number
3 2 i++
3 6 number = i * number
4 6 i++
4 24 number = i * number
5 24 i++
5 24 falls out of loop since i < 5 is now false

Number of ways to form an amount with certain coins

I am trying to solve this problem. http://www.lintcode.com/en/problem/coin-change-ii/#
This is the standard coin change problem solvable with dynamic programming. The goal is to find the number of ways to create an amount using an infinite set of coins, where each has a certain value. I have created the following solution :
public int change(int amount, int[] coins) {
// write your code here
int[] dp = new int[amount + 1];
dp[0] = 1;
// for(int coin : coins) {
// for(int i = 1; i <= amount; i++) {
// if(i >= coin) dp[i] += dp[i-coin];
// }
// }
for(int i = 1; i <= amount; i++) {
for(int coin : coins) {
if(i >= coin) dp[i] += dp[i-coin];
}
}
return dp[amount];
}
Why does the first for loop give the correct answer, but the second one does not? What am I missing here? Shouldn't the answer be the same? Could you provide a visual to help me "see" why the second for loop is incorrect?
When the amount = 8 and coins = [2,3,8] the output is 5 when it should be 3 when using the 2nd for loop's technique which is not correct.
Thank you.
Let's consider the loop that works first:
for(int coin : coins) {
for(int i = 1; i <= amount; i++) {
if(i >= coin) dp[i] += dp[i-coin];
}
}
Each iteration of the outer loop takes a coin of one value and finds out the number of ways to reach any value between the coin value and amount, adding that coin to the result of the previous iterations.
Considering your amount = 8 and coins = [2,3,8] example:
The array is initialized to
index 0 1 2 3 4 5 6 7 8
value 1 0 0 0 0 0 0 0 0
which means that without any of the coins, the only amount we can reach is 0, and we have a single way to reach that amount (0 2s, 0 3s, 0 8s).
Now we find the amounts we can reach with just the coin of value 2:
index 0 1 2 3 4 5 6 7 8
value 1 0 1 0 1 0 1 0 1
It's not surprising that we can reach any even amount. For each such amount we have a single way to reach that amount (1 2s to reach 2, 2 2s to reach 4, etc...).
Now we find the amounts we can reach with coins of value 2 or 3. We can reach an amount k using a single coin of 3 if we already found ways to reach the amount k-3.
Below I show the number of ways to reach each value between 0 and 8, and specify how many coins of each type are used in each combination.
index 0 1 2 3 4 5 6 7 8
value 1 0 1 1 1 1 2 1 2
0x2 - 1x2 0x2 2x2 1x2 3x2 2x2 4x2
0x3 - 0x3 1x3 0x3 1x3 0x3 1x3 0x3
or or
0x2 1x2
2x3 3x3
Finally, in the last iteration we consider the coin of 8. It can only be used to reach the amount 8, so we get the final result:
index 0 1 2 3 4 5 6 7 8
value 1 0 1 1 1 1 2 1 3
When you swap the loops:
for(int i = 1; i <= amount; i++) {
for(int coin : coins) {
if(i >= coin) dp[i] += dp[i-coin];
}
}
you bring the order the coins are added into play. For example, the amount 5 can be reached by either first taking a coin of 2 and then a coin of 3, or by first taking a coin of 3 and then a coin of 5. Therefore the value of dp[5] is now 2.
Similarly, dp[8] results in 5 since you can take any of the following sequences of coins:
2+3+3
3+2+3
3+3+2
2+2+2+2
8
The original loop doesn't distinguish between 2+3+3, 3+2+3 and 3+3+2. Hence the different output.
private static int coinChange(int[] coins, int sum) {
int size = coins.length;
int[][] arr = new int[size + 1][sum + 1];
// Applying the recursive solution:
for(int i = 1; i < size +1; i++){
for(int j = 1; j < sum +1; j++) {
arr[i][0] = 1;
if (coins[i - 1] > j) {
arr[i][j] = arr[i - 1][j];
} else
arr[i][j] = arr[i - 1][j]+arr[i][j - coins[i - 1]] ;
}}
return arr[size][sum];enter code here

Palindrome program, cannot terminate loop, Project Euler #4

import java.util.ArrayList;
public class Euler4{
public static void main(String [] args){
int size = 0;
int product = 0;
for(int i = 102; i > 100; i--){
for(int j = 102; j > 100; j--){
ArrayList<Integer> digits = new ArrayList<Integer>();
product = i*j;
int index = 0;
while(product > 0){
digits.add(index,product%10);
product /= 10;
index++;
}
for(int element : digits)
System.out.println("digits :" + element);
size = digits.size() - 1;
if(test(0,size,digits)){
System.out.println("i and j " + i + " " + j);
break;
}
}
}
}
public static boolean test(int i, int size, ArrayList<Integer> digits){
if(digits.get(size).equals(digits.get(i))){
if(size == i || size - i == 1){
return true;
}else{
System.out.println("i: " + i + " size: " + size + " digits#i: " + digits.get(i) +" digits#size " + digits.get(i));
size--;
i++;
if(!test(i, size, digits))
return false;
}
}
return false;
}
}
Here's the output:
digits :4 index: 0
digits :0 index: 1
digits :4 index: 2
digits :0 index: 3
digits :1 index: 4
digits :2 index: 0
digits :0 index: 1
digits :3 index: 2
digits :0 index: 3
digits :1 index: 4
digits :2 index: 0
digits :0 index: 1
digits :3 index: 2
digits :0 index: 3
digits :1 index: 4
digits :1 index: 0
digits :0 index: 1
digits :2 index: 2
digits :0 index: 3
digits :1 index: 4
i: 0 size: 4 digits#i: 1 digits#size 1
i: 1 size: 3 digits#i: 0 digits#size 0
I think there's a problem with the while loop and a problem with the recursion. The values that get ran through the test() method is the last set of values that goes into the array and that is 10201 so then even though the while loop messed up, the recursive method should still have returned true. I don't know why it's not.
This is the problem:
http://projecteuler.net/problem=4
Thanks.
EDIT: I fixed it up to be a bit more efficient and to give the max palindrome instead of just listing palindromes. Here's the final if anyone is interested: http://pastebin.com/qJUpZVzK
Your third call to test is returning true, but your second call to test is not using that value. It's falling to the bottom of the method and returning false, when you actually want it to return true.
When you call test recursively, you want to return true (from test) if the recursive call returned true.
Change
if(!test(i, size, digits))
return false;
near the bottom, to
return test(i, size, digits);
Your loop will never reach 0, because the condition will always be satisfied.
while(product > 0){
digits.add(index,product%10);
product /= 10;
index++;
}
To be honest, I think the easiest way to check for palindromes is this:
public boolean palindrome (int n) {
return String.valueOf(n).equals(new StringBuilder(String.valueOf(n)).reverse().toString());
}
The problem lies here:
while(product > 0){
digits.add(index,product%10);
product /= 10;
index++;
}
product can never be reduced to a negative number, (less than 0), by dividing by 10; which means that you will never exit this while loop. Lets look at this further:
1- product is created and it's value is 102*102=10404. (The first time through the for loops.)
2- product is divided by 10 to get 1040.4
3- While loop is checked, 1040.4 > 0, enter again.
4- product is divided by 10 to get 104.04
5- While loop is checked, 104.04 > 0, enter again.
Repeat steps 4 and 5 infinitely, because even if you keep dividing below 1, it will always be above 0. (Eg. 0.0000000000000010404 > 0)

java - looping through values

I am trying to create a nested for loops that will generate all the pairs in a range specified by the user, ranging from negative values to positive values. It is a little tough to explain, but here is the code I have:
public class test method {
public static void main (String[] args) {
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
int c = 3;
int d = 4;
for (int i = -a; i <= a; i++)
for (int j = -b; j <= b; j++) {
System.out.println(a+" and "+b+" vs "+c+" and "+d+"\n");
}
}
}
Given command line arguments 1 and 2, my desired output would be something like:
-1 and -2 vs 3 and 4
-1 and -1 vs 3 and 4
-1 and 0 vs 3 and 4
-1 and 1 vs 3 and 4
-1 and 2 vs 3 and 4
0 and -2 vs 3 and 4
0 and -1 vs 3 and 4
0 and 0 vs 3 and 4
0 and 1 vs 3 and 4
0 and 2 vs 3 and 4
1 and -2 vs 3 and 4
1 and -1 vs 3 and 4
1 and 0 vs 3 and 4
1 and 1 vs 3 and 4
1 and 2 vs 3 and 4
I assume the lack of brackets in the first for is a problem in the copy & paste, but if that's your real code you've got a problem there.
a = Math.abs(a);
b = Math.abs(b);
for (int i = -a; i <= a; i++) {
for (int j = -b; j <= b; j++) {
System.out.println(i+" and "+j+" vs "+c+" and "+d+"\n");
}
}
Two things. First of all you should be printing i and j and second you should also consider negative values. Your for's will fail since -a if a = -1 will result in
for (int i = 1; i <= -1; i++)
The condition will not be met and the iteration won't take place. By doing Math.abs you get the absolute value of the inputs and you can do the iteration from that negative value to the positive one. If both a and b are positive the abs method will return the same values (assigning a and b with the same values they already have).
Whatever should be done with c and d remains to be seen. Your desired output says you leave them as they are so I won't touch them by now.
looks reasonable, exception for the '-a' business (and printing the wrong variables)
Assuming a/b are always positive, try
for (int i = (0-a); i <= a; i++)
for (int j = (0-b); j <= b; j++) {
System.out.println(i+" and "+j+" vs "+c+" and "+d+"\n");

Java: Multi Dimensional array output confusion?

public class VarNoOfCols {
public static void main(String[] args) {
int a[][] = new int[3][];
a[0]=new int[3];
a[1]=new int[2];
a[2]=new int[1];
int temp=3;
for(int i =0; i<3;i++) {
for(int k=0;k<temp;k++) {
a[i][k]= k*10;
temp-- ;
}
}
}
}
--- output that I assumed ---- is below ---But this is incorrect.
(0 0) 0 (0 1) 10
(1 0) 0 (1 1) 10
(2 0) 0 (2,1) 10
I know this is incorrect. (My question is - on completing second iteration, "k" is greater than "temp" and when conditon fails it will stop the inner statments and do the next job (what ever it suppose to be).Why am i getting (0,2) = 20 and why i dont see (2,1) = 10 ?
You can see the correct output:
(0 0) 0 (0 1) 10 (0 2) 20
(1 0) 0 (1 1) 10
(2 0) 0
I am a learner and i really appreciate someone's help here. thank you
Change the code like that:
for(int i =0; i<3;i++)
{
for(int k=0;k<3;k++)
a[i][k]= k*10;
}
If you wanted a square output, why do you use the control variable temp that will change the number of outputted entries on each iteration over i?
this is because the temp and the k
in your program first i=0
k=0,temp=3 then (0 0) so output 0*10 = 0
k=1,temp=2 then (0 1) so output 1*10 = 10
k=2,temp=1 condition false in for loop (there the condition in the outer for loop(having i) is correct but in the inner for loop the condation k
i=1
k=0,temp=3 then (1 0) so output 0*10 = 0
k=1,temp=2 then (1 1) so output 1*10 = 10
i=2
k=0,temp=3 then (2 0) so output 0*10 = 0
k=1,temp=2 then (2 1) so output 1*10 = 10
there is no need of temp. to get correct output use this
for(int i =0; i<3;i++)
{
for(int k=0;k<3;k++)
a[i][k]= k*10;
}
Actually with your last edit (with temp-- in the second for) you obtain neither the first nor the second output.
Why?
Because you never reassign temp and after 3 time be decremented the second loop will not be executed anymore. So you got a value for (0;0) (0;1) and (1;0) only.
Why you can't obtain output 1 (square one)?
a[2] have a size of 1 so you can't have something in (2;1)
How to obtain the second output?
Don't put the temp-- in the second loop but after the second loop (at the end of the first loop).
public class VarNoOfCols {
public static void main(String[] args) {
int a[][] = new int[3][];
a[0]=new int[3];
a[1]=new int[2];
a[2]=new int[1];
int temp=3;
for(int i =0; i<3;i++)
{
for(int k=0;k<temp;k++)
//the inner for lopp doesn't have curly "{" braces.
//temp will be 3 for 1st loop and when k becomes 3 it exit inner loop.
a[i][k]= k*10;
temp--;
}
//temp--;
//System.out.println("temp : " +temp + " \n " );
}
}
Thank you guys. I figuered out the logic behind. it is not logic, it is just that { that should be watched. I will get following output if I don't use braces { in inner loop:
(0 0 ) 0 (0 1 ) 10 (0 2 ) 20
(1 0 ) 0 (1 1 ) 10
(2 0 ) 0
If the braces { and } present in inner loop with temp variable inside inner loop then I will get the following output:
(0 0 ) 0 (0 1 ) 10
(1 0 ) 0

Categories

Resources