Prime numbers in a given range with less complexity - java

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
}
}
}

Related

Program that displays every perfect number

My code runs but for one of the tests two outputs are printed when I only need one. I am unsure of how to avoid this.
This is the task:
Write an application that displays every perfect number from 2 through 1,000. A perfect number is one that equals the sum of all the numbers that divide evenly into it. For example, 6 is perfect because 1, 2, and 3 divide evenly into it and their sum is 6; however, 12 is not a perfect number because 1, 2, 3, 4, and 6 divide evenly into it, and their sum is greater than 12.
The provided template lays out the initial for loop to check each number beginning from 2 and going up to 1,000. In this for loop, the perfect() method is called, where you will submit your piece of code to test if each number follows the conditions described above.
Set result to true if it meets those conditions and use sum to add up the numbers divisible by int n in the method's parameter.
public class Perfect{
public static void main (String args[]){
final int MAX = 1000;
for(int i = 2; i <= MAX; i++)
if(perfect(i) == true)
System.out.println("The number " + i + " is perfect");
}
public static boolean perfect(int n){
int sum = 1;
int i;
boolean result = false;
for (i = 2; i < n / 2; i++) {
if (n % i == 0) {
sum += i;
}
}
if (sum == i) {
return true;
}
else {
return false;
}
}
}
My output:
The number 496 is perfect
The number 729 is perfect
Expected output:
The number 496 is perfect
It only expects the first line printed...
You need to compare sum to the original number n, not to i. And you need to add 1 to the loop condition or it will miss the last divider in even numbers
public static boolean perfect(int n){
int sum = 1;
for (int i = 2; i < (n / 2) + 1; i++) {
if (n % i == 0) {
sum += i;
}
}
return sum == n;
}
First, I don't know if you have used the correct formula. But, you should know that the first perfect number are 6, 28, 496 and 8128. 729 is not a perfect number.
Hope it helped.
public static void main(String[] args) {
int i, j, s;
System.out.println("Perfect numbers 1 to 1000: ");
for(i=1;i<=1000;i++){
s=0;
for(j=1;j<i;j++){
if(i%j==0){
s=s+j;
}
}
if(i==s){ //if i == s is perfect
System.out.println(i);
}
}
}
}
According to the question, you have to print all perfect numbers.
I have created a small snippet, try it and see.
public void printPerfect() {
for(int i=2;i<1000;i++) {
List<Integer> l =factors(i);
int sum =0;
for (Integer factor : l) {
sum+=factor;
}
if(sum==i) {
System.out.println("perfect-- " +i);
}
}
}
List<Integer> factors(int number) {
List<Integer> l = new ArrayList<Integer>();
for(int i = 1; i <= number; ++i) {
if (number % i == 0) {
if(i!=number)
l.add(i);
}
}
return l;
}
You checked sum == i instead of sum == n.
As 729 = 3^6 : 3, 243, 9, 81, 27.
public static boolean perfect(int n) {
int sum = 1;
for (int i = 2; i <= n / 2 && sum <= n; i++) {
if (n % i == 0) {
sum += i;
}
}
return sum == n;
}

Java Array saving prime numbers and using it to find next prime

I have a small problem understanding what my teacher wants me to do. What I have made is a code that saves me all the Prime numbers in an Array that can be displayed. But now he wants me to "optimize" the code with, as far as I understand, try to divide a number only by the numbers that are prime. For example : if I have 2,3,5 the next number to be prime is the number that doesn't divide by any of this. So I don't have to try 2,3,4,5 but only 2,3,5 (the numbers that I have in the array). And for example : 2,3,4,5,7 are primes, 10 is not because it divides by 2 then it has to jump on the next number.
public static void main(String[] args) {
String introducedNumber = JOptionPane.showInputDialog("Introduce a number"); //with JOptionPane imported will ask you a small box for a number
int number, divider, numberDividing; //declaring the int's
number = Integer.parseInt(introducedNumber); //converting the input to a int
int x = 0; //starting X to 0 since its 1st array position
int[] arrayPrime = new int[number]; //declaring and creating an array
for (divider = 1; divider <= number; divider++) { //for to run till numbers
//for that checks if the number divides by any other than himself
for (numberDividing = 2; (numberDividing < divider) && (divider % numberDividing != 0); numberDividing++) {
}
if (numberDividing >= divider) {
arrayPrime[x] = divider;
x++;
}
}
for (int i = 0; i < x; i++) {
System.out.println(arrayPrime[i]);
}
}
}
At the moment your code to check whether a number is prime is:
for (numberDividing = 2; (numberDividing < divider) && (divider % numberDividing != 0); numberDividing++) {
}
if (numberDividing >= divider) {
arrayPrime[x] = divider;
x++;
}
So it is checking all numbers from 2 to the last prime. But there's no need for it to do that: it only needs to check the primes you already have in your array.
To make your code a bit more readable, I suggest moving your check to a separate private method. I've also renamed x to primeCount:
private boolean isPrime(int number) {
for (int i = 0; i < primeCount; i++) {
if (number % arrayPrime[i] == 0)
return false;
}
return true;
}
Then your calling code becomes:
for (int divider = 2; divider <= number; divider++) {
if (isPrime(divider))
arrayPrime[primeCount++] = divider;
}
There is another fairly trivial optimisation you can do. You don't need to check any primes that are greater than the square root of the test number because you've already checked smaller factors at that point:
private boolean isPrime(int number) {
for (int i = 0; i < primeCount; i++) {
int prime = arrayPrime[i];
if (prime * prime > number)
break;
else if (number % prime == 0)
return false;
}
return true;
}
If you don't want to use a separate method, then:
for (int divider = 2; divider <= number; divider++) {
boolean isPrime = true;
for (int i = 0; i < primeCount && isPrime; i++) {
isPrime = number % arrayPrime[i] > 0;
}
if (isPrime)
arrayPrime[primeCount++] = divider;
}
And, for your future study, here's a more elegant way to achieve the same result using a prime number generator:
public class PrimeGenerator {
private long current = 1;
private final List<Long> primes = new ArrayList<>();
public long next() {
do {
current++;
} while (primes.stream().anyMatch(n -> current % n == 0));
primes.add(current);
return current;
}
}
You were right that you only need to divide new numbers by previously discover primes. What I do below is simply loop through all the discovered primes and use a boolean to keep track of if each number is prime. I also use an ArrayList instead of an array so that there are not numerous unused blocks like in your original array. Hope this helps!
ArrayList<Integer> arrayPrime = new ArrayList<Integer>(); //use array list instead of static array
arrayPrime.add(2); //seed first prime number
boolean isPrime; //boolean to determine if prime
for (divider = 3; divider <= number; divider++) { //loop up to input number, starting at 3
isPrime = true; //initialize true for each new number
for (i = 0; i < arrayPrime.size(); i++) { //loop through each previous prime
if (divider % arrayPrime[i] == 0) { //see if number is divisible by previous prime
isPrime = false;
break; //break out of loop
}
}
if(isPrime){ //if it did not divide evenly, it is prime
ArrayPrime.add(divider);
}
}
System.out.println(list);

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.

How can I make ProjectEuler 23 Solution faster

This is what I have. It is solving the problem, but taking forever. Can I divide the last loop 0 to 28123 into half and run them simultaneously somehow to make it faster, and then in the end add the two sums to get the final result? Will "thread" help? What can I do to make the code solve faster?
/*
A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.
A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.
As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.
Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.
*/
public class power {
public static void main(String[] args){
System.out.println(bigSum());
}
public static boolean isPerfect(int a){
boolean perfect = false;
int sum = 0;
for(int i = 1; i<(a/2)+1; i++)
{
if (a%i == 0)
{
sum = sum + i;
}
}
if(a == sum){
perfect = true;
}
return perfect;
}
public static boolean isAbundant(int a){
boolean Abundant = false;
int sum = 0;
for(int i = 1; i<(a/2)+1; i++)
{
if (a%i == 0)
{
sum = sum + i;
}
}
if(a < sum){
Abundant = true;
}
return Abundant;
}
public static boolean isDeficient(int a){
boolean Deficient = false;
int sum = 0;
for(int i = 1; i<(a/2)+1; i++)
{
if (a%i == 0)
{
sum = sum + i;
}
}
if(a > sum){
Deficient = true;
}
return Deficient;
}
public static boolean isSumOfTwoAbundant(int a){
boolean SumOfTwoAbundant = false;
for(int i = 1; i<a; i++){
if(isAbundant(i) && isAbundant(a-i)){
SumOfTwoAbundant = true;
}
}
return SumOfTwoAbundant;
}
public static long bigSum(){
int sum = 0;
for(int i = 0; i<28123; i++){
if(!isSumOfTwoAbundant(i)){
sum = sum + i;
System.out.println("i: " + i + "; " + "Sum: " + sum);
}
}
return sum;
}
}
You're recomputing whether every number < a is abundant with every call of isSumOfTwoAbundant. Try keeping a list of abundant numbers and add to it when you find one. Then you can loop through that list rather than rechecking for abundance for numbers < a. Something like:
public static boolean isSumOfTwoAbundant(int a){
boolean SumOfTwoAbundant = false;
if(isAbundant(a))
{
abundants.add(a);
}
for(int i = 0; i<abundants.length; i++) {
for(int j = 0; j < abundants.length; j++) {
if(a - abundants[i] == abundants[j]){
SumOfTwoAbundant = true;
}
}
}
return SumOfTwoAbundant ;
}
private ArrayList<int> abundants;
There are a lot of other ways to make this better, too, but Project Euler is about learning those through experience.
Another Java solution: (takes less than a second)
static int sum_Of_Divisors(int n){
int limit = n;
int sum = 0;
for(int i=1;i<limit;i++){
if(n%i==0){
if(i!=1){
if(i != n/i) sum += (i + n/i);
else sum += i;
}
else
sum += i;
limit = n/i;
}
}
return sum;
}
static boolean isAbundant(int n){
int sum = sum_Of_Divisors(n);
return sum>n;
}
static boolean sum_of_Two_Abundant(int n, HashSet<Integer> abundant){
for(Integer i:abundant){
if(abundant.contains(n-i)) return true;
}
return false;
}
static long q23(){
long sum = 0;
HashSet<Integer> abundant = new HashSet<Integer>();
for(int i=2;i<=28123;i++){
if(isAbundant(i))
abundant.add(i);
}
for(int i=1;i<=28123;i++)
if(!sum_of_Two_Abundant(i, abundant)) sum+=i;
return sum;
}

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