Project Euler #3 in Java; program not outputting result - java

I am trying solve problem 3 in Project Euler:
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
This is my code:
import java.util.ArrayList;
public class Test {
public static void main(String[] args){
long max = 600851475143L;
ArrayList<Long> primes = new ArrayList<>();
primes.add((long) 2);
boolean prime = true;
for (long i = 3; i <= max; i += 2){
for (long j = 3; j < Math.sqrt(i); j++){
if (i % j == 0){
prime = false;
break;
}
}
if (prime) primes.add(i);
else prime = true;
}
for (int i = primes.size() - 1; i >= 0; i--){
if (max % primes.get(i) == 0){
System.out.println(primes.get(i));
return;
}
}
}
}
The code is not outputting anything, it just gives me a blank screen. Please do not solve the problem for me, just tell me what the bug is that is preventing it from outputting anything.

You are wasting time calculating all the primes when you don't have too.
When you find the first prime, try reducing max by that prime until it is not longer divisible.
Then continue finding the next prime.
and reducing max by factoring out that prime.
each time check to see if max is equal to the current prime. If so, you are done.
Assuming you are finding primes correctly (which I believe you are) consider the following:
primes = 2,3,5,7,11,13
max = 99
is 99 divisible by 2 - no, try next prime.
is 99 divisible y 3 - yes
max = 33
is 33 divisble by 3 - yes
max = 11
is 11 divisible by 3 - no
by 5 - no
by 7 - no
by 11 - hey, max is a prime! And it must be the largest because
it can't be reduced anymore.
And if you want, when finding each prime factor of max, save it in a list.
Then multiply all the values in the list to see if the product == max.
Here is your code
import java.util.ArrayList;
public class Test {
public static void main(String[] args){
long max = 600851475143L;
// right here, reduce max by current prime (which starts at 2)
for (long i = 3; i <= max; i += 2){
boolean prime = true;
for (long j = 3; j < Math.sqrt(i); j++){
if (i % j == 0){
prime = false;
break;
}
}
if (prime) {
// right here, reduce max by current prime
}
}
}
}

Are you sure your program is completing? Iadded the following code below and it looks like the first for loop is going to take a long time to complete, which may be why you aren't seeing any output. To see your progress, try adding in a print statement like below:
import java.util.ArrayList;
public class Test {
public static void main(String[] args){
long max = 600851475143L;
ArrayList<Long> primes = new ArrayList<Long>();
primes.add((long) 2);
boolean prime = true;
for (long i = 3; i <= max; i += 2){
if(i % 1000005 == 0)
System.out.println("i = " + i);
for (long j = 3; j < Math.sqrt(i); j++){
if (i % j == 0){
prime = false;
break;
}
}
if (prime) primes.add(i);
else prime = true;
}
for (int i = primes.size() - 1; i >= 0; i--){
if (max % primes.get(i) == 0){
System.out.println(primes.get(i));
return;
}
}
}
}

Related

why do we use < and not <= in second loop while printing prime numbers

Below is the code snipent
first loop contains numbers from 1 to 100 and second loop to iterate through numbers , in second loop if we use <= prime numbers are not getting printed
public class primeNumbers {
public static void main(String args[]) {
int i, number, count;
System.out.println("Prime Numbers from 1 to 100 are : ");
for (number = 1; number <= 100; number++) {
count = 0;
for (i = 2; i <= number; i++) {
if (number % i == 0) {
count++;
break;
}
}
if (count == 0 && number != 1) {
System.out.print(number + " ");
}
}
}
}
We know that
Every natural number has both 1 and itself as a divisor. If it has any other divisor, it cannot be prime.
from https://en.wikipedia.org/wiki/Prime_number.
In addition to this, it is only necessary to loop from 2 until the square root of the number you are testing (explained here).
This way we can write the second loop as:
for (i = 2; i <= Math.sqrt(number); i++) {
It is only necessary to discover if there is any natural number that is a divisor of number between 2 and Math.sqrt(number) - inclusively. If this is the case, number is not a prime. Otherwise it is a prime.
E.g.: Let's see the case where number = 4. We already know that the number 4 has 1 and itself (4) as divisors. So, we want to loop from 2 to Math.sqrt(4) = 2 to discover if there are any more divisors. And in this case in the first iteration where i = 2, we find that (4 % 2) == 0. So 4 is not prime.
This would be written like this:
public static void main(String[] args) {
System.out.println("Prime Numbers from 1 to 100 are:");
for (int number = 2; number <= 100; number++) {
boolean isPrime = true;
for (int i = 2; i <= Math.sqrt(number); i++) {
if (number % i == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
System.out.print(number + " ");
}
}
}
prime numbers are divisible by 1 and itself. The second loop run from 2, which means that when you check one number is divisible by itself, that does not make sense. using " < " is optimise

Java : Not sure if correct use of BigInteger

This program is meant to calculate the sum x amount of prime numbers under n, yet my code doesnt seem to work, it compiles and there are no errors.When I run it the console is just blank
public static void main(String[] args) {
Prime prime = new Prime();
BigInteger answer = BigInteger.valueOf(0);
for (int i = 2; i < 2000000; i++) {
if (prime.isPrime(i)) {
answer = answer.add(BigInteger.valueOf(i));
}
}
System.out.println(answer);
}
isPrime method
boolean isPrime(int n) {
for(int i = 2; i < n ; i++) {
if(n % i == 0) {
return false;
}
}
return true;
}
You are just not waiting long enough.
Try using i < 200 and you'll see the answer 4227 print out quite quickly.
You are checking 2,000,000 numbers for primality. Your isPrime method is O(n) so you are doing approximately 2,000,000 * 1,000,000 calculations. You work it out.
Why not use isProbablePrime() method from BigInteger class, if you using it anyway ?
for (int i = 2; i < 2000000; i++) {
if (new BigInteger(Integer.toString(i)).isProbablePrime(10)) {
answer = answer.add(BigInteger.valueOf(i));
}
}
This code runs only for around 4 seconds.
But if you want to do by your method, you should optimize it. It's necessary to check for divisors until sqrt(n)
for(int i = 3; i * i <= n ; i+= 2) {
if(n % i == 0) {
return false;
}
}
Or you can use the Sieve of Eratosthenes to solve your problem

Prime numbers in a given range with less complexity

I have used below programs to find first n prime numbers (in below program it is from 2 to n). Can we write a program with single for loop? I also tried recursive approach but it is not working for me.
public static void main(String[] args) {
// Prime numbers in a range
int range = 15;
int num = 1;
int count = 0;
boolean prime = true;
while (count < range) {
num = num + 1;
prime = true;
for (int i = 2; i <= num / 2; i++) {
if (num % i == 0) {
prime = false;
break;
}
}
if (prime) {
count++;
System.out.println(num);
}
}
}
i dont think you can reduce it to one loop. But you can improve your code as Luca mentioned it.
public class PrimeFinder {
private final List<Integer> primes;
private final int primeCapacity;
public PrimeFinder(final int primeCapacity) {
if (primeCapacity < 3) {
throw new IllegalArgumentException("Tkat is way to easy.");
}
this.primeCapacity = primeCapacity;
primes = new ArrayList<>(primeCapacity);
primes.add(2);
}
public void find() {
final Index currentNumber = new Index();
while (primes.size() < primeCapacity) {
if (!primes.stream().parallel().anyMatch(prime -> (currentNumber.value % prime) == 0)) {
primes.add(currentNumber.incremet());
} else {
currentNumber.incremet();
}
}
}
public List<Integer> getPrimes() {
return primes;
}
private class Index {
public int value = 3;
public int incremet() {
return value++;
}
}
public static void main(String[] args) {
PrimeFinder primeFinder = new PrimeFinder(100000);
final long start = System.currentTimeMillis();
primeFinder.find();
final long finish = System.currentTimeMillis();
System.out.println("Score after " + (finish - start) + " milis.");
primeFinder.getPrimes().stream().forEach((prime) -> {
System.out.println(prime);
});
}
}
main rule here is simple, if given number isnt clearly divided by any prime number that you already have found, then it is prime number.
P.S. dont forget that primes.strem().... is loop also, so it is not a one loop code.
P.S.S. you can reduce this much further.
to understand the complexity of your algorithm you don't have to count the number of inner loops but the number of times you are iterating over your elements. To improve the performance of your algorithm you need to investigate if there are some iterations that could be unnecessary.
In your case when you do
for (int i = 2; i <= num / 2; i++) you are testing your num against values that are not necessary.. ex: if a number is divisible by 4 it will be by 2 too.
when you do for (int i = 2; i <= num / 2; i++) with num = 11
i will assume the values 2,3,4,5. 4 here is a not interesting number and represent an iteration that could be avoided.
anyway according to wikipedia the sieve of Eratosthenes is one of the most efficient ways to find all of the smaller primes.
public class PrimeSieve {
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
// initially assume all integers are prime
boolean[] isPrime = new boolean[N + 1];
for (int i = 2; i <= N; i++) {
isPrime[i] = true;
}
// mark non-primes <= N using Sieve of Eratosthenes
for (int i = 2; i*i <= N; i++) {
// if i is prime, then mark multiples of i as nonprime
// suffices to consider mutiples i, i+1, ..., N/i
if (isPrime[i]) {
for (int j = i; i*j <= N; j++) {
isPrime[i*j] = false;
}
}
}
// count primes
int primes = 0;
for (int i = 2; i <= N; i++) {
if (isPrime[i]) primes++;
}
System.out.println("The number of primes <= " + N + " is " + primes);
}
}
I don't know any way use a single loop for your question, but I do see two places where you can reduce the complexity:
Cache the prime numbers you found and use these prime numbers to decide if a number is prime or not. For example, to decide if 11 is a prime number, you just need to divide it by 2,3,5,7 instead of 2,3,4,5,6,...10
You don't need to check till num/2, you only need to check till the square root of num. For example, for 10, you only need to check 2,3 instead of 2,3,4,5. Because if number n is not prime, then n = a * b where either a or b is smaller than the square root x of n). If a is the smaller one, knowing that n can be divided by a is enough to decide that n is not prime.
So combining 1 & 2, you can improve the efficiency of your loops:
public static void main(String[] args) {
// Prime numbers in a range
int range = 15;
int num = 1;
int count = 0;
boolean prime = true;
ArrayList<Integer> primes = new ArrayList<>(range);
while (num < range) {
num = num + 1;
prime = true;
int numSquareRoot = (int) Math.floor(Math.pow(num, 0.5));
for (Integer smallPrimes : primes) {// only need to divide by the primes smaller than num
if (numSquareRoot > numSquareRoot) {// only need to check till the square root of num
break;
}
if (num % smallPrimes == 0) {
prime = false;
break;
}
}
if (prime) {
System.out.println(num);
primes.add(num);// cache the primes
}
}
}

Effective way of find Total number of even divisors of the number

I have to find number of even number of divisor of given number. For this i tried.I am getting correct output but i am getting time complexity more than required.Question :- First line contains the number of testcases T, followed by T lines each containing an integer N output should be - For each testcase, print the required answer in a single line.How can i reduce complexity for this given code.Or can anyone please suggest more efficient way...
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class TestClass {
public static void main(String args[]) throws Exception {
// Read input from stdin and provide input before running
String frt = "";
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
int T = Integer.parseInt(line);
int[] inp = new int[T];
for (int i = 0; i < T; i++) {
int x = Integer.parseInt(br.readLine());
inp[i] = x;
}
int[] ans = new int[T];
int count = 1;
for (int i = 0; i < T; i++) {
int x = inp[i];
if (x % 2 == 0) {
for (int j = 2; j <= x / 2; j = j + 2) {
if (x % j == 0)
count++;
}
} else
count = 0;
ans[i] = count;
}
for (int i = 0; i < T; i++)
System.out.println(ans[i]);
}
}
import java.io.*;
class Ideone
{
public static void main (String[] args) throws Exception
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
int i,j,k,n;
int[] inp = new int[T];
for (i = 0; i < T; i++) {
inp[i] = Integer.parseInt(br.readLine());
}
//Find all the primes numbers till the square-root of 10^9.
int MAX, root, arrLen;
MAX=1000000000;
arrLen=(int)Math.sqrt(MAX); // arrLen=31622
boolean[] primes=new boolean[arrLen+2]; // No need to find all the primes numbers till MAX
primes[0]=primes[1]=false;
for(i=2;i<arrLen;i++)
primes[i]=true;
// Using Sieve of Eratosthenes
// Square root of 31622 is 177.8
root=(int)Math.sqrt(arrLen); // root=177
for(i=2;i<=root;i++)
{
if(primes[i])
{
n=i*i;
k=0;
//arrLen is the length of primes array.
for(j=n; j<arrLen; k+=1, j=n+(i*k))
primes[j]=false;
}
}
int[] ans = new int[T];
for( i = 0; i < T; i++) {
n = inp[i];
if(n%2==1)
{
ans[i]=0; // Odd numbers will have 0 even divisors
}
else
{
int[] facts=new int[50];
for(k=0;k<50;k++)
facts[k]=1;
facts[0]=0; // fact[0] will contain the highest power of 2 that divides n.
while(n%2==0)
{
facts[0]+=1;
n=n/2;
}
// Prime factorizing n
j=1;
for( k=3; k<arrLen; k+=2)
{
if(primes[k] && n%k==0)
{
while(n%k==0)
{
facts[j]+=1;
n=n/k;
}
j+=1;
}
if(n==1) // To check if n has been completely divided or not.
break;
}
if(n!=1) // To check if there is any prime factor greater than the square root of MAX.
{
facts[j]+=1;
j+=1;
}
int count=1;
for(k=0;k<j;k++)
count=count*facts[k];
ans[i]=count;
}
}
for ( i = 0; i < T; i++)
System.out.println(ans[i]);
}
}
I am of the feeling that this question might have been posted on any competitive coding platform, probably like HackerEarth. If so, then please don't post direct questions on StackOverFlow(in my opinion).
Anyways, I have tested my code and it runs correctly.
In questions where you are not able to reduce time complexity, first make sure that unnecessary objects are not created. Object creation in the memory is a time consuming operation. Avoid irrelevant creation of object and variables. The code above can still be optimized, but that will reduce it's readability. :)
Also before approaching a problem, try to figure out various test cases. Like odd numbers will have 0 even divisors. So by checking whether a number is odd, can reduce several operations.
A bit more explanation to the above code:
Number Of Divisor of A Number are: (N1+1)(N2+1)(N3+1).... Where N1,N2,N3 etc are Powers Of Prime Multiples of the number.
Now if N1 is for 2(the only even prime number),
then Number of Even Divisors of the Number are: N1*(N2+1)*(N3+1)...
In the facts[] array, facts[0] corresponds to N1, while N2, N3 etc are stored in facts[1],facts[2], etc.
facts[0] is initialized with 0, while others are initialized with 1.
The count stores the final product: N1*(N2+1)*(N3+1)... which is equal to the number of Even divisors of the original number.
There is a very simple trick for this,first compute the prime factorization of 720,which is 2^4×3^2×5,the total number of factors here is 3x2×5=30, and number of odd factors (number of factors of the odd primes)=3×2=6,subtracting gives number of even factors = 24.This method works for any number.
NOTE: If the number has no odd factors i.e,the prime factorization is of the form 2a,then the number of number of even factors is a and number of odd factors is 1.
My solution, shorter and simpler:
public class Solution {
public static int numberOfEvenDivisors(int n) {
if (n % 2 == 1)
return 0;
int evenDivisors = 0;
for (int i = 1; i < Math.sqrt(n) + 1; i++) {
if ((i % 2 == 0) && (n % i == 0))
evenDivisors++;
if ((n % (n / i) == 0) && (n / i) % 2 == 0)
evenDivisors++;
if ((i * i == n) && (i % 2 == 0))
evenDivisors--;
}
return evenDivisors;
}
public static void main(String[] args) {
//test here
}
}
Here is short explanation:
When n is odd we return 0, there are no even divisors.
In the first if we check whether i is a divisor and whether i is even. When yes, wo do increment the divisors counter. Note that we start with 1. This is necessary because here we know that n is even and n is its own divisor.
In second if we increment divisors counter if n / i is even and i is a divisor. If i is even, we counted it already in first if. And we know that (n/i) >= i, because we count i only up to square root of n.
And in the last, third if we check the case whether i is a even divisor that is square root of n (for example i == 4, n == 16). Here we decrement number of divisors because we do not want to count same divisor twice. That is.
P.S. We assume n >= 1.
This for loop
for (int i = 0; i < T; i++) {
int x = inp[i];
if (x % 2 == 0) {
for (int j = 2; j <= x / 2; j = j + 2) {
if (x % j == 0)
count++;
} else
count = 0;
ans[i] = count;
}
could be changed to
for (int i = 0; i < T; i+=2) {
int x = inp[i];
for (int j = 2; j <= x / 2; j = j + 2) {
if (x % j == 0)
count++;
if(count != 1)
count = 0;
ans[i] = count;
}
so that it will make the for loop run half as many times.

Loops and Prime Numbers

Write a program that prompts the user for an integer and then prints out all prime numbers up to that integer. For example, when the user enters 20, the program should print
2 3 5 7 11 13 17 19
Recall that a number is a prime number if it is not divisible by any number except 1 and itself.
I am trying to write this program but I am having difficulties, can anyone show me how to write this code?
This is what I have written but it is completely wrong.
import java.util.Scanner;
public class PrimeNumbers
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
System.out.print("Enter Integers: ");
int x;
int n = in.nextInt();
for (int i = 2; i < n ; i++)
{
x = i;
if (n % i != 0 && i % x != 0)
{
System.out.println(i);
}
x--;
}
}
}
Computes the number of primes less than or equal to N using
the Sieve of Eratosthenes.
% java PrimeSieve 25
The number of primes <= 25 is 9
% java PrimeSieve 100
The number of primes <= 100 is 25
% java -Xmx100m PrimeSieve 100000000
The number of primes <= 100000000 is 5761455
% java PrimeSieve -Xmx1100m 1000000000
The number of primes <= 1000000000 is 50847534
The 110MB and 1100MB is the amount of memory you want to allocate
to the program. If your computer has less, make this number smaller,
but it may prevent you from solving the problem for very large
values of N.
class PrimeSieve {
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
// initially assume all integers are prime
boolean[] isPrime = new boolean[N + 1];
for (int i = 2; i <= N; i++) {
isPrime[i] = true;
}
// mark non-primes <= N using Sieve of Eratosthenes
for (int i = 2; i*i <= N; i++) {
// if i is prime, then mark multiples of i as nonprime
// suffices to consider mutiples i, i+1, ..., N/i
if (isPrime[i]) {
for (int j = i; i*j <= N; j++) {
isPrime[i*j] = false;
}
}
}
// count primes
int primes = 0;
for (int i = 2; i <= N; i++) {
if (isPrime[i]){ primes++; System.out.print(i+", ");}
}
System.out.println("\nThe number of primes <= " + N + " is " + primes);
}
}
Use this method to check if a given int is a prime.
public static boolean isPrime(int a)
{
if ( a == 2)
return true;
int midpoint = Math.round(a/2);
for(int i = 2; i < midpoint; i++)
{
if(a % i == 0)
return false;
}
return true;
}
Explanation:
Loop through all the numbers until midpoint and modulus until you encounter 0 or not. If you encounter 0 then return false because we know that it is not prime, if we encounter no zero then we return true because it is prime.
We loop until midpoint because there is no need to loop further.
You can implement it in your loop via
for (int i = 2; i < n ; i++)
{
if (isPrime(i))
{
System.out.println(i);
}
}

Categories