Strange bug with Catalan number generator - java

I'm trying to write a iterative catalan number generator as opposed to a recursive one. It works, but only up until the number "10", and then it starts to print out numbers that don't make sense. Here's what I have so far.
public static long dpr1(int n)
{
long [] Array = new long[(2*n)+1];
Array[0]=1;
Array[1]=1;
int count=0;
long c=0;
for(int i = 2; i<=(2*n); i++){
Array[i]=(i)*(Array[i-1]);
count=i;
}
return(((Array[count])/(((Array[n]))*(Array[n])))/(n+1));
}
I've been testing it using this as a main:
public class CatalanTest
{
public static void main(String[] args)
{
long startTime, endTime, result;
for (int n = 2; n < 18; n = n + 2)
{
System.out.println(Catalan.dpr1(n));
}}}
Which returns
2
14
132
1430
16796
-2
97
0
Which are the corresponding Catalan numbers for the even numbers between 2 and 10, but after that the values don't make a ton of sense and I have no idea why. Any help sorting this out would be appreciated.

Based on this code A[i] is equal to Factorial(i). When n=11, you calculate Factorial up to 22, and Factorial(22) is larger than the max value of long, so your calculations overflow, and the result is wrong.
You can avoid the overflow is you realize that:
(Array[count] / (Array[n]*Array[n])) / (n+1) =
((2*n)!/(n!*n!))/(n+1) =
((n+1)*(n+2)*...*(2n)/(n!))/(n+1)=
(n+2)*(n+3)*...*(2n)/(n!)
So you can forget about your array and just calculate this formula, which would work without overflowing for larger values of n.
Your entire code can be reduced to :
for (long n=2;n<18;n+=2) {
long res = 1;
for (long l=n+2;l<=2*n;l++)
res *= l;
for (long l=2;l<=n;l++)
res=res/l;
System.out.println(res);
}
Which produces this output (it looks like we still get an overflow for n=16):
2
14
132
1430
16796
208012
2674440
91351
To avoid that, we can combine the multiplications and divisions, in order to keep the intermediate result small :
for (long n=2;n<18;n+=2) {
double res = 1;
for (long l=n+2;l<=2*n;l++) {
res *= l;
res /= (l-n);
}
System.out.println((long)res);
}
This produces :
2
14
132
1430
16796
208012
2674440
35357670

Related

How do I approach this recursively in Java?

In this program I need to get input from the user that indicates the length of the numbers with this quality: The number should be prime and if you delete each digit from the right the number that is left should still be prime. i.e. 2399 is such a number. Because 2399 is prime, and also 239, and 23, and 2. So if the input is 3, all the numbers with this length and this quality should be printed. I have a simple code but it works too slow for integers with a length greater than 4.
Edited: Actually each of these numbers is made from the previous set numbers with smaller length, i.e. {2,3,5,7} by adding 1 digit to each and checking if the number which is produced is prime or not.
This will produce the next set of numbers {23,29,33,...}
That's why I'm looking for a recursive solution in order to prevent the linear search in the main class which is making the program too slow.
import java.util.*;
public class Main {
public static boolean isPrime(int n) {
for (int i = 2; i < n; i++)
if (n % i == 0)
return false;
if(n==1)
return false;
return true;
}
public static int digitCount(int n){
int count = 0;
while(n!=0){
n /= 10;
++ count;
}
return count;
}
public static int countPrimesubnum(int n) {
int count = 0;
while(n>0) {
if(isPrime(n) == true){
count ++;
}
n/=10;
}
return count;
}
public static void isWanted(int n){
if (countPrimesubnum(n) == digitCount(n))
System.out.println(n);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int a = (int)Math.pow(10,n-1);
int b = (int)Math.pow(10,n);
int c = b-1;
for (int i=a; i<c; i++){
isWanted(i);
}
}
}
Using recursion alone won't help you a lot. What you need is to reuse the values that you have already computed. For this, you could use recursion. First of all, as others already mentioned, you should rewrite your isPrime function to iterate only between 2 to sqrt(n). Doing this will improve your performance a little bit.
But back to your problem with computing if the exact number is prime or not! Imagine if you want to search 3 digit numbers. For instance, you should compute if 23 is prime or not 11 times. But if you want to search 4 digit numbers, you have to call the isPrime function for number 23 more than 100 times, Which will drastically reduce your performance.
My approach is to build from what you have to solve this problem. I would compute all primes with the feature you want with length n-1 and add numbers 1, 3, 7, 9 at the end. This way, you only use the isPrime function once per number.
Here is the performance comparison between my approach and yours in my local machine(MacBook Pro 2019). In both cases, I used the same isPrime function:
n
Your Execution time
My Execution Time
3
2 mili seconds
14 mili seconds
4
5 mili seconds
14 mili seconds
5
18 mili seconds
14 mili seconds
6
248 mili seconds
14 mili seconds
7
5.5 seconds
14 mili seconds
8
2 minutes and 32 seconds
15 mili seconds
9
didn't get an answer after 30 minutes
14 mili seconds.
As you can see, the execution time of my code doesn't change much when the input gets larger, but your performance drastically decreases with larger inputs.
I've attached both of our codes, so your code compares the performance. It is written in Kotlin, not Java, to understand the algorithm when converting it back to Java. To understand what I've done you just need to take a look at function findRecursivePrimes and findNewPrimes.
#ExperimentalTime
#JvmStatic
fun main(args: Array<String>) {
val n: Int = 9
val absoluteValueWithoutDP = measureTime {
val a = 10.0.pow((n - 1).toDouble()).toInt()
val b = 10.0.pow(n.toDouble()).toInt()
val c = b - 1
for (i in a until c) {
isWanted(i)
}
}.absoluteValue
val absoluteValueWithDP = measureTime {
val allPrimesOfLenN: List<Int> = findRecursivePrimes(n)
for (element in allPrimesOfLenN) {
println(element)
}
}.absoluteValue
println("run time of base algorithm : $absoluteValueWithoutDP")
println("run time of improved algorithm : $absoluteValueWithDP")
}
private fun findRecursivePrimes(n: Int): List<Int> {
val allPrimesOfLenN: List<Int> = if (n == 1) {
listOf(2, 3, 5, 7)
} else {
val allPrimesOfLenNMinusOne = findRecursivePrimes(n - 1)
findNewPrimes(allPrimesOfLenNMinusOne)
}
return allPrimesOfLenN
}
private fun findNewPrimes(allPrimesOfLenNMinusOne: List<Int>): List<Int> {
var allPrimesOfLenN: List<Int> = emptyList()
for (prime in allPrimesOfLenNMinusOne) {
val primeTimesTen = prime * 10
for (i in listOf(1, 3, 7, 9)) {
val n = primeTimesTen + i
if (isPrime(n)) {
allPrimesOfLenN = allPrimesOfLenN.plus(n)
}
}
}
return allPrimesOfLenN
}
private fun isPrime(n: Int): Boolean {
for (i in 2 until sqrt(n.toDouble()).toInt()) if (n % i == 0) return false
return n != 1
}
fun digitCount(n: Int): Int {
var n = n
var count = 0
while (n != 0) {
n /= 10
++count
}
return count
}
fun countPrimesubnum(n: Int): Int {
var n = n
var count = 0
while (n > 0) {
if (isPrime(n)) {
count++
}
n /= 10
}
return count
}
fun isWanted(n: Int) {
if (countPrimesubnum(n) == digitCount(n)) println(n)
}
First of all read on primality tests. The simplest method described is trial division, what you are using, but almost. The max number to check is square root of n, not n - 1. Implement it like this, and you will see dramatic increase in performance.
If speed is still not enough, you can make further optimizations:
Keeping a cache of primes, because you currently you are checking a number more than once for primality
Also in this line - for (int i = 2; i < n; i++), you need to check only other primes, not every number
You could add even/odd check before loop, even numbers are never prime, only odd might be.
All those optimizations a mentioned will lead to increase in performance, especially the first one. Using recursion certanly will not, as answered here.

Why do I get a negative output when I run my program to compute the sum of all even Fibonacci numbers?

Background:
I'm working on Project Euler problem #2 and I have a class built to solve the problem. For those who haven't done this before, this is the problem:
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... .
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
The problem:
I have the program built to solve the problem given, but when I run it, I get the value -1833689714. This should not be the value returned, as I sum only positive numbers and no multiplications are performed that I know of. How do I fix this?
My code
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
int answer = resultsSum(fibonacci(4000000));
System.out.println(answer);
}
public static int resultsSum(ArrayList<Integer> resultList){
int total = 0;
for(Integer r : resultList){
total += r.intValue();
}
return total;
}
public static ArrayList<Integer> fibonacci(int n){
ArrayList fibEvens = new ArrayList<Integer>();
int a = 1;
int b = 2;
fibEvens.add(b);
for(int i = 1; i < (n - 1); i++) {
int tempVar = a;
a = b;
b += tempVar;
if(b % 2 == 0){
fibEvens.add(b);
}
}
return fibEvens;
}
}
https://projecteuler.net/problem=2
The reason you're getting a negative result is that the the terms of the Fibonacci sequence above the 88th term are in excess of the maximum positive value of the Long data type in java, which is 9,223,372,036,854,775,80.
When you attempt to increment the long data type beyond it's max value by one it wraps around to the minimum value (-9,223,372,036,854,775,80). At the point the Fibonacci terms exceed the max value, you're doing this many times over.
Additionally, the problem you've posted indicates that you should be stopping when the value of the number derived from the sequence is greater than 4 million, not trying to add the even values of the first 4 million values (which is huge).
It looks like your code is attempting to get to the 4-millionth Fibonacci number, which is quite different than the terms in the Fibonacci sequence whose values do not exceed four million.
Because
int data type stores number from -2^31 to 2^31 - 1
Integer data type stores number from -2^63 to 2^63 - 1
Try with BigInteger
public static BigInteger fibonacci(int n) {
BigInteger[] f = new BigInteger[n + 1];
f[0] = BigInteger.ZERO;
if (n > 0) {
f[1] = BigInteger.ONE;
}
for (int i = 2; i < f.length; i++) {
f[i] = f[i - 1].add(f[i - 2]);
}
return f[n];
}
But the 4 million Fibonacci value very long. See more 300th, 500th

Java program to print exponential series for numbers 3 and 5 and limit the result to below 1000

I am new to Java programming and have tried a few problems on Project Euler. I somehow came up with my own problem of printing sequence of exponents of 3 and 5 and limit the result to below 1000. I have researched for 3 days to find the best approach to this problem but I could not find relevant articles. I have come across algorithms on exponential series but those were too advanced for my capability right now.
I would appreciate any help in solving this problem. Please see the code I have tried
public class Exponent {
public static void main (String[] args) {
// Declared integers for base and exponent
int i = 0; /* for base */
int n = 0; /* for exponent */
for (n=1; n<5; n++) {
for (i=1; i<=5; i++) {
if (i%3 == 0 || i%5 == 0) {
System.out.println(Math.pow(i,n));
}
}
}
}
}
This code prints out the following result:
3.0
5.0
9.0
25.0
27.0
125.0
81.0
625.0
My problem is that it is very apparent that I am forcing the exponent to print below 1000 by limiting the base and exponent value inside the loop
for (n=1; n<5; n++) //because n<=5 would print result for 5 power 5 which is 3125
I would like to somehow limit the result to below 1000 so not sure if this declaration is apt
int result = 1000; // result variable as 1000
Also, I want the code to print the output in alternates of 3 and 5 as shown below. My program prints the output in sequence of 3 and 5 respectively.
Desired output:
3.0
5.0
9.0
27.0
125.0
81.0
625.0
243.0
729.0
And stops there because the next value would exceed 1000.
I also wanted to know if there is any other approach instead of using Math.pow() method because it returns a double instead of an int. I would like to avoid the double value and just print as follows:
Without double:
3
5
9
27
81
125
243
625
729
Without using Math.pow() (and printing in different order ):
int[] bases = { 3, 5 };
long maxval = 1000L;
for (int base : bases) {
long value = base;
do {
System.out.println( value );
value *= base;
} while (value < maxval);
}
First create a double to store the result:
double result = 0;
Then create an infinite while loop which calculates the result using 3 and 5 and breaks out once result is above 1000.
while(true)
{
result = Math.pow(3, n);
if(result > 1000)
{
break;
}
System.out.println(((int)result));
result = Math.pow(5, n);
if(result < 1000)
{
System.out.println((int)result);
}
n++;
}
Since exponents of 3 are smaller than 5 don't break out until the maximum exponent in 3 is hit. Since the break does not occur don't print the 5 unless it is valid.
Also to print the double as an int value just cast it to an int.
EDIT:
If you are really worried about efficiency here is a faster solution:
public void calcExponents(int max)
{
int resultThree = 3;
int resultFive = 5;
while(resultThree < max)
{
System.out.println(resultThree);
if(resultFive < max)
{
System.out.println(resultFive);
}
resultThree *= 3;
resultFive *= 5;
}
}
You could also make the 3 and 5 arguments to take it one step further.
Why not check if the result is bigger than 1000, and just break out of the loop if it is?
if(Math.pow(i,n)>=1000)
break;
Hint:
3.0 = 3^1
5.0 = 5^1
9.0 = 3^2
25.0 = 5^2 // I assume you forgot it
27.0 = 3^3
125.0 = 5^3
81.0 = 3^4
625.0 = 5^4
243.0 = 3^5
729.0 = 3^6
and 3x is always smaller than 5x. So a single loop (for the x part) with two computations in the body of the loop one for 3 and one for 5 should do the job. You just have to use some condition for the less than 1000 part to avoid printing 55 and 56.
You could use a single loop, checking exponents for both 3 and 5 on each iteration, and printing each result that is less than 1000.
You just want to make sure that you break the loop once your 3's exceed 1000.
To print integer values, you can simply cast the result of Math.pow() to an int.
There are many different ways that one could write an algorithm like this. Here's a very simple (untested) example:
public class Exponent {
public static void main (String[] args) {
int i = 1; // or start at 0 if you prefer
// set the max value (could also be parsed from args)
int maxValue = 1000;
// the break condition also increments:
while (Math.pow(3, i++) < maxValue) {
int x3 = (int) Math.pow(3, i);
int x5 = (int) Math.pow(5, i);
if (x3 < maxValue) {
System.out.println(x3);
}
if (x5 < maxValue) {
System.out.println(x5);
}
}
}
}

Competitive Programing: Factorial Time limit exceeded

I am working on a very simple spoj problem in which we have to take input N calculate its factorial then find out number of trailing zeros and display it some thing like
Sample Input:
6
3
60 // fact of 60 has 14 trailing zeros
100
1024
23456
8735373
Sample Output:
0
14
24
253
5861
2183837
so i have written a code which is working fine on my machine but when i am submitting it is giving me time limit error. i don't know how to make this code fast. So i want suggestions from you guys.
public class Factorial {
public static void main(String[] args) throws IOException {
try {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(bf.readLine());
for (int i = 0; i < t; i++) {
Long num = Long.parseLong(bf.readLine());
BigInteger bd = BigInteger.valueOf(num);
System.out.println(countTrailinZeros(factorial(bd.toString())));
}
} catch (IllegalStateException e) {
return;
}
}
public static BigInteger factorial(String n) {
BigInteger x = BigInteger.valueOf(1);
for (long i = 1; i <= Integer.parseInt(n); i++) {
x = x.multiply(BigInteger.valueOf(i));
}
return x;
}
public static int countTrailinZeros(BigInteger bd) {
String s = bd.toString();
int glen = s.length();
s = s.replaceAll("[0.]*$", "");
int llen = s.length();
return glen - llen;
}
}
I have googled about some possible solutions and found out that lookup table may work i don't have much idea about this. I'd be very thankful if some can explain me about lookup table.
edit: Could it be java is too slow to solve this problem in given time? or in general it is not favorable to use java for competitive programing?
you dont need to calculate factorial to get number of trailing zeroes.
Solution :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int lines = Integer.parseInt(br.readLine());
int sum, N, p;
for (int i = 0; i < lines; i++) {
N = Integer.parseInt(br.readLine());
sum = 0;
p = 5;
while (N / p != 0) {
sum = sum + N / p;
p = p * 5;
}
System.out.println(sum);
}
}
}
Logic is :
The highest power of a prime number p in N! is given by
floor(N/p) + floor(N/p*p) + floor(N/p*p*p) ... so on till [floor(N/p^n) = 0]
so since number of ending zeroes is required , ans = min(max power of 2 in N!, max power of 5 in N!)
because zeroes appears on multiplication by ten and ten can be decomposed to 10 = (2 * 5).
It is fine to assume that max power of 5 in N! is always less than max power of 2 in N!.
as multiples of 2 occur more frequently than multiples of 5.
So problem reduces to finding max power of 5 in N! and hence the solution.
Example :
N = 5
max power of 5 in 5! = floor(5/5) + floor(5/25) => 1 + 0 => ans = 1
N = 100
max power of 5 in 100! = floor(100/5) + floor(100/25) + floor(100/125) => 20 + 4 + 0 => ans = 24
I have solved the same problem in spoj platform, you just have to divide the value by 5 until the value becomes less than 5. print all the result of the division and that's your output.
To solve this problem, consider prime factorization of N factorial:
N! = 2^a1 * 3^a2 * 5^a3 * .... where a1, a2, a3, ... >= 0
Since N! = N*(N-1)(N-2)..., multiples of 2 are more frequent than 5.
So, a1 >= a3 in this expansion.
Number of trailing zeros = how many times you can divide N! by 10.
Which implies, ans = min(a1, a3) based on the prime factorization given above.
Since we already proved a1 >= a3, hence ans = a3, i.e power of 5 in the prime factorization of N!.
There will be floor(N/5) numbers that will contribute to power of 5 atleast once.
There will be floor(N/25) numbers that will contribute to power of 5 atleast twice.
There will be floor(N/125) numbers that will contribute atleast thrice
and so on.
The total power of 5 = floor(N/5) + floor(N/25) + floor(N/125) + ...
Implementation of this formula in code is left as an exercise.

Factorial loop results are incorrect after the 5th iteration

I am currently taking pre-calculus and thought that I would make a quick program that would give me the results of factorial 10. While testing it I noticed that I was getting incorrect results after the 5th iteration. However, the first 4 iterations are correct.
public class Factorial
{
public static void main(String[] args)
{
int x = 1;
int factorial;
for(int n = 10; n!=1; n--)
{
factorial = n*(n-1);
x = x * factorial;
System.out.printf("%d ", x);
}
}//end of class main
}//end of class factorial
That is an Integer Overflow issue. Use long or unsigned long instead of int. (And as #Dunes suggested, your best bet is really BigInteger when working with very large numbers, because it will never overflow, theoretically)
The basic idea is that signed int stores numbers between -2,147,483,648 to 2,147,483,647, which are stored as binary bits (all information in a computer are stored as 1's and 0's)
Positive numbers are stored with 0 in the most significant bit, and negative numbers are stored with 1 in the most significant bit. If your positive number gets too big in binary representation, digits will carry over to the signed bit and turn your positive number into the binary representation of a negative one.
Then when the factorial gets bigger than even what an unsigned int can store, it will "wrap around" and lose the carry-over from its most significant (signed) bit - that's why you are seeing the pattern of sometimes alternating positive and negative values in your output.
You're surpassing the capacity of the int type (2,147,483,647), so your result is wrapping back around to the minimum int value. Try using long instead.
Having said the that, the method you are currently employing will not result in the correct answer: actually, you are currently computing 10! ^ 2.
Why complicate things? You could easily do something like this:
long x = 1L;
for(int n = 1; n < 10; n++)
{
x *= n;
System.out.println(x);
}
1
2
6
24
120
720
5040
40320
362880
which shows successive factorials until 10! is reached.
Also, as others have mentioned, if you need values bigger than what long can support you should use BigInteger, which supports arbitrary precision.
Your formula for the factorial is incorrect. What you will have is this:
Step 1 : n*(n-1) = 10 * 9 = 90 => x = 1*90 = 90
Step 2 : n*(n-1) = 9 * 8 = 72 => x = 90*72 = 6480 or, it should be : 10 * 9 * 8 => 720
But the wrong results are coming from the fact that you reached the maximum value for the type int as pointed out by others
Your code should be
public class Factorial
{
public static void main(String[] args)
{
double factorial = 1;
for(int n = factorial; n>=1; n--)
{
factorial = factorial * n;
System.out.printf("%d ", factorial );
}
}
}
In addition to what the other answers mention about the overflow, your factorial algorithm is also incorrect. 10! should calculate 10*9*8*7*6*5*4*3*2*1, you are doing (10*9)*(9*8)*(8*7)*(7*6)*...
Try changing your loop to the following:
int x = 1;
for(int n = 10; n > 1 ; n--)
{
x = x * n;
System.out.printf("%d ", x);
}
You will eventually overflow if you try to calculate the factorial of higher numbers, but int is plenty large enough to calculate the factorial of 10.

Categories