Palindrome program, cannot terminate loop, Project Euler #4 - java

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)

Related

"while" loop not iterating correctly

I am supposed to print the following output by using loops:
1
2 1
3 2 1
4 3 2 1
5 4 3 2 1
6 5 4 3 2 1
7 6 5 4 3 2 1
The highest number in this pattern (in this example, 7) is determined by user input. Here is the applicable code for the pattern:
index=patternLength+1; n=1; //These values are all previously intitialized
while (index!=1) {
index--;
printSpaces((index*2)-2); //A static method that prints a certain number of spaces
while(n!=1) {
n--;
System.out.print(n + " ");
}
System.out.print("\n");
n=patternLength+1-index;
}
And here is the incorrect output for the user input "7":
1
2 1
3 2 1
4 3 2 1
5 4 3 2 1
There are two blank lines preceding the incorrect output; these lines have the correct number of spaces necessary for the complete/correct pattern, but for some reason, the actual numbers start printing too "late" in the loop. In other words, the spaces that appear before the "1, 2 1" in the correct example are in the incorrect output. It's some of the numbers that are missing and make the incorrect example incorrect.
OK, I got it.
index=patternLength+1; n=1;int nSetter=1;
//Loop C
System.out.println("Pattern C:");
while (index!=1) {
index--;
printSpaces((index*2)-2);
while(n!=0) {
System.out.print(n + " ");
n--;
}
System.out.print("\n");
nSetter++;
n = nSetter;
}
My problem was that my "n" needed to go both up and down, so the extra variable "nSetter" seems to have solved that, although this may be a round-about solution. Whatever. Thanks to #Andreas for pointing me in the correct direction and #JohnKugelman for the helpful edit.
Please try this code your second while loop is not correct.
int index = patternLength + 1;
int n = 2; //These values are all previously intitialized
int i = 1;
while (index != 1) {
index--;
printSpaces((index * 2) - 2); //A static method that prints a certain number of spaces
while (n != 1) {
n--;
System.out.print(n + " ");
}
System.out.print("\n");
i++;
n = i+1;
}

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

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

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

Sum of numbers using recursion java

Let's say n = 4. With recursion I want to return:
1 1 1 1
1 1 2
1 3
2 1 1
2 2
3 1
4
Basically I want to take number n and with by combining numbers 1,2,3 and 4 create all possible variations when the number of sum == n.
This was my first idea, but it gives me
Exception in thread "main" java.lang.StackOverflowError
public static void test_2(String path, int sum, int n){
if(sum == n){
System.out.println(path);
} else {
test_2(path+"1 ", sum + 1, n);
test_2(path+"2 ", sum + 2, n);
test_2(path+"3 ", sum + 1, n);
test_2(path+"4 ", sum + 2, n);
}
}
The main problem is that you are always recursing when sum != n. When the sum gets bigger than n, you never stop, hence the StackOverflowError This means we need to add a check and terminate when the sum gets bigger:
public static void test_2(String path, int sum, int n) {
if (sum == n) {
System.out.println(path);
} else if (sum < n) { // <-- only recurse if the sum is less than the target
test_2(path+"1 ", sum + 1, n);
test_2(path+"2 ", sum + 2, n);
test_2(path+"3 ", sum + 3, n);
test_2(path+"4 ", sum + 4, n);
}
}
As a side-note, in your 2 last calls, you wrote 1 and 2 instead of 3 and 4, but that was probably just a typo.
Output from calling test_2("", 0, 4):
1 1 1 1
1 1 2
1 2 1
1 3
2 1 1
2 2
3 1
4
But do note that your current code is not very dynamic: it wouldn't work if you were to give values greater than 4 for n. I would suggest refactoring it a little.

Doing a factorial with only one while loop

I'm trying to find the factorial of 9 down to 0, only using one while loop, but my idea isn't outputting a value.
I figured out the way to do it using two while loops:
int i;
count = 9;
while (count >= 0){
value = count;
i = count-1;
while (i > 0){
value = value * i;
i--;
}
System.out.print(value + ", ");
}
This worked but I've tried to change it to use only one while loop and got this:
int i;
for (count = 9; count < 0; count--){
value = count;
i = count-1;
while (i > 0){
value = value * i;
i--;
}
System.out.print(value + ", ");
}
I'm not completely sure if I'm using the for statement correctly but I think I am, or at least I think it should output something so I can debug it.
Could someone give me a hint in the right direction?
This will give you all the factorials from 9 down to 1 :
int i=1;
int value=1;
String res = "";
while (i <= 9){
value = value * i;
res = value + ((i>1)?",":"") + res;
i++;
}
System.out.print(res);
Output :
362880,40320,5040,720,120,24,6,2,1
Perhaps it's cheating, since I'm calculating the factorials in ascending order from 1! to 9!, but I'm reversing the order of the output in order to get the required result.
Edit :
If you also want 0! to be printed, a small change can do the trick :
int i=1;
int value=1;
String res = "";
while (i <= 10){
res = value + ((i>1)?",":"") + res;
value = value * i;
i++;
}
System.out.print(res);
Output :
362880,40320,5040,720,120,24,6,2,1,1
First, the reason why your second loop doesn't work is that you have the wrong condition in the for. The condition in the middle is one that will cause the loop to continue, not to stop. So what you were saying was "start from 9, and work while the number is less than 0". But of course, your number is greater than zero to begin with.
Second, I believe using a for loop is a little bit of cheating, because a for loop is just a specific case of while loop.
Now to the problem of the factorial itself. You know that a factorial n! is defined as (n-1)!*n.
The basic loop for calculating one specific factorial is:
int n = 5;
int factorial = 1;
while ( n > 0 ) {
factorial *= n;
n--;
}
System.out.println( "Factorial is: " + factorial );
This will give you the factorial of five. But it's not exactly based on the formula we are talking about. There is another way to calculate it, starting from 1:
int n = 5;
int factorial = 1;
int count = 1;
while ( count <= n ) {
factorial *= count;
count++;
}
System.out.println( "Factorial is " + factorial );
The interesting part about this way of doing it is that in every stage of the loop, factorial is actually the value (count-1)! and we are multiplying it by count. This is exactly the formula we were talking about.
And the good thing about it is that just before you did it, you had the value of the previous factorial. So if you printed it then, there you'd get a list of all the factorials along the way. So here is a modified loop that prints all the factorials.
int n = 9;
int factorial = 1;
int count = 0;
while ( count < n ) {
System.out.println( "Factorial of " + count + " is " + factorial );
count++;
factorial *= count;
}
System.out.println( "Factorial of " + n + " is " + factorial );
Note that I modified it a little more so that it will work with zero. The factorial of zero is a special case so we shouldn't multiply by zero - that will make all the factorials wrong. So I changed the loop to multiply only after I increase count to 1. But this also means that you have to print the final factorial out of the loop.
Just first assign value=i, then run your loop. You can get the factorial with only while loop.
Important: Because n!=n*(n-1)!, therefore, i-- should must be perform before value = value * i.
public static void main(String args[]) {
int value=5;
int i=value;
while (i > 1){
i--;
value = value * i;
}
System.out.print(value);
}
Update: If you want to count factorial of 0 to 9, then use this code: (It includes factorial of 0 also)
public static void main(String args[]){
int countLowest=0;
int countHighest=9;
int value=1;
while (countLowest<= countHighest){
if(countLowest==0)
value = value * (countLowest+1);
else
value=value*countLowest;
countLowest++;
System.out.println("Factorial of "+(countLowest-1)+" is "+value);
}
}
Result:
Factorial of 0 is 1
Factorial of 1 is 1
Factorial of 2 is 2
Factorial of 3 is 6
Factorial of 4 is 24
Factorial of 5 is 120
Factorial of 6 is 720
Factorial of 7 is 5040
Factorial of 8 is 40320
Factorial of 9 is 362880
count = 9;
sum=1;
while (count >= 1){
sum*=count;
--count;
}
System.out.print(sum);
it will give you 9!=362880

Categories

Resources