How can I reduce my function runtime [closed] - java

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
In this code I wanted solve Project Euler Problem #3. The objective is to find the biggest prime number. My code is running right but there is a problem at runtime. How can I reduce run time? Can anyone suggest any tips?
public class Euler3 {
//https://www.hackerrank.com/contests/projecteuler/challenges/euler003
public static void main(String[] args) {
long[] inputs = readInputs();
for (int i = 0; i < inputs.length; i++) {
System.out.println(findBiggestPrime(inputs[i]));
}
}
public static boolean isPrime(long num) {
if (num == 2)
return true;
for (long i = 3; i * i <= num; i += 2) {
if (num % i == 0)
return false;
}
return true;
}
private static long[] readInputs() {
Scanner scanner = new Scanner(System.in);
int inputQuantities = scanner.nextInt();
long[] inputs = new long[inputQuantities];
for (int i = 0; i < inputQuantities; i++) {
inputs[i] = scanner.nextLong();
}
return inputs;
}
private static long findBiggestPrime(long number) {
long biggestPrime = 0;
if (number % 2 == 0) {
number = number / 2;
biggestPrime = 2;
}
if (number == 2)
return 2;
for (int i = 3; i <= number; i += 2) {
if (number % i != 0)
continue;
if(!isPrime(i))
continue;;
biggestPrime = i;
number = number / biggestPrime;
}
return biggestPrime;
}
}

The lines
if(!isPrime(i))
continue;
will slow down your algorithm and should not be there.
Any factor you encounter in your algorithm should automatically be prime. You should not, for example, ever encounter the factor 15 because you should have already encountered 3 and 5 and divided by them both.
To make this work you should not just do number = number / biggestPrime;. When you encounter a factor you should keep dividing by it until it no longer goes into the number. This way you clear out powers.

isPrime() is hugely inefficient. Here's a version that keeps track of already-confirmed-multiples in a HashSet. I don't know what order of magnitude of #'s you are using. This seems to work with some efficiency on my machine in the ~100K range.
private static final Set<Long> multiples = new HashSet<>();
private static boolean isPrime(long l) {
if(l%2==0 && l>2)
return false;
if(multiples.contains(l))
return false;
double r = Math.sqrt(l);
for(long i=3;i<=r;++i) {
for (long j = i * 2; j <= l; j += i) {
multiples.add(j);
if (j == l) {
return false;
}
}
}
return true;
}

Related

Slow calculation of sum of primes for large datasets [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
My program that calculates the sum of primes is very slow for very large nth term. Please how do I optimize the processing time of my program? The fastest program will be appreciated and the reason why mine is slow for large sets of data. Thanks.
Here's the Java program:
public class SumOfPrimes {
public static void main(String[] args) {
primeNumber(2000000);
}
public static void primeNumber(int nth) {
int counter = 0, i = 2;
while(i>=2) {
if(isPrime(i)) {
counter += i;
}
i++;
if(i == nth) {
break;
}
}
System.out.println(counter);
}
public static boolean isPrime(int n) {
boolean prime = true;
int i;
for(i= 2; i < n; i++) {
if (n % i == 0) {
prime = false;
for (int j = 3; j * j < n; j += 2) {
if (n % j == 0) prime = false;
}
}
}
return prime;
}
}
Well, it's unclear why you have an inner for loop in your isPrime. Removing it will save much time.
Besides, once you find that n is not prime, you should return immediately. Either break out of the loop, or just return false.
Another optimization would be not to test all the number until i < n. It's enough to test until i * i <= n.
public static boolean isPrime(int n) {
int i;
for(i = 2; i * i <= n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
Remember primes you have found, and only test them.
Remove the inner loop.
Test 2, 3, then all odds.
Something like...
public boolean isPrime( ArrayList<Long> primes, long n ){
for( Long t : primes ){
if( n % t == 0 ){
return false;
}
if( t * t > n )return true;
}
return true;
}
public void sumOfPrimes()
{
ArrayList<Long> primes = new ArrayList<Long>();
long n;
double count = 0;
for( n = 2; n < 2000000; n++ ){
if( isPrime( primes, n ) ){
primes.add( n );
count += n;
}
}
}
This should be your isPrime function-
bool isPrime (int number) {
if (number < 2) return false;
if (number == 2) return true;
if (number % 2 == 0) return false;
for (int i=3; (i*i) <= number; i+=2) {
if (number % i == 0 ) return false;
}
return true;
}
Putting together all the answers to my question above, my program has been re-written and it is much faster for very large datasets.
public class SumOfPrimes {
public static void main(String[] args) {
primeNumber(2000000);
}
public static void primeNumber(int nth) {
int i = 2;
long counter = 0;
while(i>=2) {
if(isPrime(i)) {
counter += i;
}
i++;
if(i == nth) {
break;
}
}
System.out.println(counter);
}
public static boolean isPrime (int n) {
if (n < 2) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
for (int i=3; (i*i) <= n; i+=2) {
if (n % i == 0 ) return false;
}
return true;
}
}
#aega's solution for the isPrime function did the trick. Now 2 million datasets can be calculated for less than 2 secs.
We no need to test from 1 to n, even 3 to n/2 or 3 to sqrt(n) is also too much for testing for a bigger number.
To make the testing the least, we can only test n with the previous prime that have been found up to sqrt(n), like what mksteve has mentioned.
static List<Integer> primes = new ArrayList<>();
static boolean isPrime (int number) {
if (number < 2) return false;
if (number == 2) return true;
if (number % 2 == 0) return false;
int limit = (int) Math.sqrt(number);
for (i : primes) {
if (i > limit) break;
if (number % i == 0 ) return false;
}
return true;
}
public static void primeNumber(int nth) {
int i = 2;
long counter = 0;
while(i <= nth) {
if(isPrime(i)) {
counter += i;
primes.add(i);
}
i++;
}
System.out.println(counter);
}
A faster program will be to store the generated prime numbers in an array and use only those elements for divisibility check. The number of iterations will reduce dramatically. An element of self-learning is there in this.
I don't have time right now. But, when I'm free, will write a java code to implement this.
Use the power of Lambda for dynamic functional referencing and streams for optimized performance with inbuilt filter conditions.
public static boolean isPrime(final int number) {
return IntStream.range(2,(long) Math.ceil(Math.sqrt(number + 1))).noneMatch(x -> number % x == 0);
}

Mysterious number 6174 [Kaprekar Theorem] in Java [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
In 1949 the mathematician D. R. Kaprekar, devised a process now known as Kaprekar's operation. First choose a four digit number where the digits are not all the same (that is not 1111, 2222,...). Then rearrange the digits to get the largest and smallest numbers these digits can make. Finally, subtract the smallest number from the largest to get a new number, and carry on repeating the operation for each new number.
Let's try it out, starting with the number 2005, the digits of last
year. The maximum number we can make with these digits is 5200, and
the minimum is 0025 or 25 (if one or more of the digits is zero, embed
these in the left hand side of the minimum number)
5200 - 0025 = 5175
7551 - 1557 = 5994
9954 - 4599 = 5355
5553 - 3555 = 1998
9981 - 1899 = 8082
8820 - 0288 = 8532
8532 - 2358 = 6174
Now Objective is verify this theorem & find the number of iteration take to reach 6174.
Can anyone give a better algorithm? Here is my code.
public int VerifyKaprekarTheorem(int m) {
if (m <= 1000 || m > 9999) {
return -1;
}
String orginal = String.valueOf(m);
int count = 0;
while (true) {
int Max = Integer.parseInt(sortString(orginal, false));
int Min = Integer.parseInt(sortString(orginal, true));
count++;
int diff = Max - Min;
if (diff == 6174) {
break;
}
orginal = String.valueOf(diff);
}
return count;
}
public static String sortString(String Source, boolean assendingOrder) {
char[] original = String.valueOf(Source).toCharArray();
Arrays.sort(original);
if (assendingOrder) {
return new String(original);
}
char[] dessending = new char[original.length];
for (int i = original.length - 1; i >= 0; i--) {
dessending[i] = original[(original.length - 1) - i];
}
return new String(dessending);
}
and testcase
public void testCase01() {
int actual = VerifyKaprekarTheorem(4321);
assertEquals(3, actual);
}
I have change Integer to String then char array than sorting again Integer conversion.
public int VerifyKaprekarTheorem(int m) {
if (m <= 1000 || m > 9999) {
return -1;
}
int count = 0;
while (true) {
int Max = largestNumber(m);
int Min = smallestNumber(m);
count++;
m = Max - Min;
if (m == 6174) {
break;
}
}
return count;
}
private static int largestNumber(int input) {
int[] numbers = new int[10];
for (int i = input; i != 0; i /= 10) {
numbers[i % 10]++;
}
int counter = 0;
int result = 0;
for (int i = 0; i < 10; counter += numbers[i++]) {
result += (int) ((Math.pow(10, numbers[i]) * i - 1) / 9) * Math.pow(10, counter);
}
return result;
}
private static int smallestNumber(int input) {
int[] numbers = new int[10];
for (int i = input; i != 0; i /= 10) {
numbers[i % 10]++;
}
int counter = 0;
int result = 0;
for (int i = 9; i >= 0; counter += numbers[i--]) {
result += (int) ((Math.pow(10, numbers[i]) * i - 1) / 9) * Math.pow(10, counter);
}
return result;
}

Java - terminate endless loop [duplicate]

This question already has answers here:
Breaking out of a for loop in Java [closed]
(5 answers)
Closed 7 years ago.
I have a block of code that I've written to give me the largest prime factor of any number.
public static void main(String[] args) {
long n = 49;
while (true) {
long x = sPrimeFactor(n);
if (x < n) n /= x;
else
System.out.println(n);
}
}
public static long sPrimeFactor (long n){
if (n <= 1) return 1;
long cap = (long) Math.sqrt(n);
for (long i = 2; i <= cap; i++) {
if (n % i == 0) return i;
}
return n;
}
As you might imagine, this locks into an endless loop where the largest prime factor of the number will just keep looping through the function.
How do I break it off when my solution has been reached?
EDIT: This was me just being silly. I should have searched it up first. In any case, this was the code that solved it:
public static void main(String[] args) {
long n = (long) 49;
while (true) {
long p = sPrimeFactor(n);
if (p < n) n /= p;
if (p == n) break;
}
System.out.println(n);
}
public static long sPrimeFactor (long n){
if (n <= 1) return 1;
long cap = (long) Math.sqrt(n);
for (long i = 2; i <= cap; i++) {
if (n % i == 0) return i;
}
return n;
}
while (true) {}
You need set a flag that make the while loop stop after you achieved your goal.
Or use break; is another way

Java code for project euler #7 gives wrong answer [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
This code is meant to find the 1001st prime but gives me the answer 47 which is clearly wrong.
public class problem7 {
public static void main(String[] args) {
int[] myarray = new int[1001];
int j = 0;
boolean prime = false;
for (int i = 2;; i++) {
for (int k = 2; k < i; k++) {
if (i == (k - 1) && i % k != 0) {
prime = true;
}
if (i % k == 0) {
prime = false;
prime = true;
}
if (prime) {
myarray[j] = i;
}
if (j == 1000) {
System.out.println(myarray[1000]);
return;
}
j++;
}
}
}
}
Any help would be greatly appreciated.
Your check for prime is wrong: you cannot declare a number prime and set prime = true based on a single test. The inner loop should set prime to false, but it shouldn't reset it to true: once it's false, it's false.
The algorithm should proceed as follows:
For each i, set prime=true
Loop over potential divisors k
If a divisor such that i % k == 0 is found, set prime = false, and break the loop
If prime is still true at the end of the nested loop, add i to the list of primes.
This should give you a correct result, at which point you should consider optimizing your solution using considerations below:
If you did not find a divisor among k below or at sqrt(i), then i is prime
You do not have to try all numbers k, only the ones from the list of primes that you have discovered so far.
I think j++ is increment only if prime number is inserted not at all case.By using this code you will be get your 1001 Prime number
public static void main(String[] args) {
int[] myarray = new int[1001];
int j = 0;
for (int i = 2;; i++) {
boolean prime = false;
for (int k = 2; k < i; k++) {
if (i % k == 0) {
prime = true;
}
}
if (!prime) {
myarray[j] = i;
j++;
}
if (j == 1001) {
break;
}
}
for (int primeNumber : myarray) {
System.out.println(primeNumber);
}
}
This is an implementation of dasblinkenlights algorithm!
public static void main(String args[]) {
int[] primes = new int[1001];
int i = 1;
int index = 0;
while (primes[1000] == 0) {
i++;
boolean skip = false;
for (int i1 : primes) {
if (i1 == 0)
break;
if (i % i1 == 0) { //checks if the number is a multiple of previous primes, if it is then it skips it
skip = true;
break;
}
}
if (!skip) {
if (isPrime(i)) {
primes[index] = i;
System.out.println(i);
index++;
}
}
}
}
static boolean isPrime(int n) {
for (int i = 2; i < n; i++) {
if (n % i == 0)
return false;
}
return true;
}
The primality test you done here is kind of ambiguous. Because the general approach is, we pick any number assuming its prime, so at the beginning, prime = true. Then if there exist any factor k of input such that k < input and kthen the number is not prime, so prime = false.
I modified your code and get a result: 104743 .
Update: Here is a bit faster way to find large prime. The inner loop will iterate up to square root of i, reason: Why do we check upto the square root of a prime number to determine if it is prime?
public static void main(String[] args) {
int[] myarray = new int[10001];
int j = 0;
boolean prime = true;
int i = 2;
while (true) {
prime = true;
for (int k = 2; k*k <= i; k ++) {
if (i % k == 0) {
prime = false;
}
}
if (prime) {
myarray[j] = i;
if (j == 10000) {
System.out.println(myarray[10000]);
return;
}
j++;
}
if(i > 4)
i += 2;
else
i++;
}
}

Project Euler #10 Java solution not working

I'm trying to find the sum of the prime numbers < 2,000,000. This is my solution in Java but I can't seem get the correct answer. Please give some input on what could be wrong and general advice on the code is appreciated.
Printing 'sum' gives: 1308111344, which is incorrect.
Edit:
Thanks for all the help. Changed int to long and < to <= and it worked flawlessly, except for being an inefficient way of finding prime numbers :)
/*
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
*/
class Helper{
public void run(){
Integer sum = 0;
for(int i = 2; i < 2000000; i++){
if(isPrime(i))
sum += i;
}
System.out.println(sum);
}
private boolean isPrime(int nr){
if(nr == 2)
return true;
else if(nr == 1)
return false;
if(nr % 2 == 0)
return false;
for(int i = 3; i < Math.sqrt(nr); i += 2){
if(nr % i == 0)
return false;
}
return true;
}
}
class Problem{
public static void main(String[] args){
Helper p = new Helper();
p.run();
}
}
The result will be too large to fit into an integer, so you are getting an overflow. Try using a BigInteger or a long instead. In this case a long is enough.
You're treating as prime those numbers that are only divisible by their square root (like 25). Instead of i < Math.sqrt(nr) try i <= Math.sqrt(nr).
That's a really inefficient way to find primes, incidentally.
Your isPrime doesn't work for squares. isPrime(9) returns true.
As already stated errors were two:
you used an int that is not big enough to hold that sum.. you should have used a long
you used < instead that <=, and it was a wrong guard for the cycle
Apart from that what you are doing is really inefficient, without going too deep inside this class of algorithms (like Miller-Rabin test) I would suggest you to take a look to the Sieve of Eratosthenes.. a really old approach that teaches how to treat a complex problem in a simple manner to improve elegance and efficiency with a trade-off of memory.
It's really cleaver: it keeps track of a boolean value for every prime up to your 2 millions that asserts if that number is prime or not. Then starting from the first prime it excludes all the successive numbers that are obtained by multiplying the prime it is analyzing for another number. Of couse more it goes and less numbers it will have to check (since it already excluded them)
Code is fair simple (just wrote it on the fly, didn't check it):
boolean[] numbers = new boolean[2000000];
long sum = 0;
for (int i = 0; i < numbers.length; ++i)
numbers[i] = true;
for (int i = 2; i < numbers.length; ++i)
if (!numbers[i])
continue;
else {
int j = i + i;
while (j < 2000000) {
numbers[j] = false;
j += i;
}
}
for (int i = 2; i < 2000000; ++i)
sum += numbers[i] ? i : 0;
System.out.println(sum);
Of course this approach is still unsuitable for high numbers (because it has to find all the previous primes anyway and because of memory) but it's a good example for starters to think about problems..
by using Sieve of Eratosthenes effectively, i solved the problem, here is my code
public class SumOfPrime {
static void findSum()
{
long i=3;
long sum=0;
int count=0;
boolean[] array = new boolean[2000000];
for(long j=0;j<array.length;j++)
{
if((j&1)==0)
array[(int)j]=false;
else
array[(int)j]=true;
}
array[1]=false;
array[2]=true;
for(;i<2000000;i+=2)
{
if(array[(int)i] & isPrime(i))
{
array[(int)i]=true;
//Sieve of Eratosthenes
for(long j=i+i;j<array.length;j+=i)
array[(int)j]=false;
}
}
for(int j=0;j<array.length;j++)
{
if(array[j])
{
//System.out.println(j);
count++;
sum+=j;
}
}
System.out.println("Sum="+sum +" Count="+count);
}
public static boolean isPrime(long num)
{
boolean flag=false;
long i=3;
long limit=(long)Math.sqrt(num);
for(;i<limit && !(flag);i+=2)
{
if(num%i==0)
{
flag=false;
break;
}
}
if(i>=limit)
flag=true;
return flag;
}
public static void main(String args[])
{
long start=System.currentTimeMillis();
findSum();
long end=System.currentTimeMillis();
System.out.println("Time for execution="+(end-start)+"ms");
}
}
and the output is
Sum=142913828922 Count=148933
Time for execution=2360ms
if you have doubt, please do tell
Here is my solution
public class ProjectEuler {
public static boolean isPrime(int i) {
if (i < 2) {
return false;
} else if (i % 2 == 0 && i != 2) {
return false;
} else {
for (int j = 3; j <= Math.sqrt(i); j = j + 2) {
if (i % j == 0) {
return false;
}
}
return true;
}
}
public static long sumOfAllPrime(int number){
long sum = 2;
for (int i = 3; i <= number; i += 2) {
if (isPrime(i)) {
sum += i;
}
}
return sum;
}
/**
* #param args
*/
public static void main(String[] args) {
System.out.println(sumOfAllPrime(2000000));
}
}

Categories