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);
Related
how can I use Java to find out numbers that can't be divided by any other number?
i have an int array:
int[] numbers = new int[25];
Now I want to iterate over this array and output all the numbers that are not divisible in a new array. The remaining numbers should no longer appear in the new array.
For example, in a range from 1-25, only the numbers [1,3,5,7,11,13,17,19,23] should be output as an array.
How exactly do I get to program this?
Thanks in advance!
Like #Selvin said in the comments, these numbers have a name, they are called "prime numbers".
For example, you can use something like this:
for (int number : numbers) {
if (!primeCal(number)) {
number = null;
}
}
private static void primeCal(int num) {
int count = 0;
for (int i = 1; i <= num; i++) {
if (num % i == 0) {
count++;
}
}
if (count == 2) {
return true;
} else {
return false;
}
}
You must first iterate and then use the following method to check if any of them are prime numbers or not
public static boolean isPrime(int n) {
if (n <= 1) {
return false;
}
for (int i = 2; i < Math.sqrt(n); i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
I am working on a assignment about so called "friendly-numbers" with the following definition: An integer is said to be friendly if the leftmost digit is divisible by 1, the leftmost two digits are divisible by 2, and the leftmost three digits are divisible by 3, and so on. The n-digit itself is divisible by n.
Also it was given we need to call a method (as I did or at least tried to do in the code below). It should print whether a number is friendly or not. However, my program prints "The integer is not friendly." in both cases. From what I have tried, I know the counter does work. I just cannot find what I am missing or doing wrong. Help would be appreciated, and preferably with an adaptation of the code below, since that is what I came up with myself.
import java.util.Scanner;
public class A5E4 {
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
System.out.print("Please enter an integer: ");
int friendlyNumber = in.nextInt();
boolean result = isFriendly(friendlyNumber);
if (result)
{
System.out.println("The integer is friendly");
}
else
{
System.out.println("The integer is not friendly");
}
}
public static boolean isFriendly(int number)
{
int counter = 1;
while (number / 10 >= 1)
{
counter ++;
number = number / 10;
}
boolean check = true;
for (int i = 1; i <= counter; i++)
{
if (number / Math.pow(10, (counter - i)) % i == 0 && check)
{
check = true;
}
else
{
check = false;
}
}
return check;
}
}
while (number / 10 >= 1){
counter ++;
number = number / 10;
}
In this bit, you are reducing number to something smaller than 10. That is probably not what you want. You should make a copy of number here.
Also, proper software design would recommend that you extract this to a dedicated method.
private int countDigits(int number){
if(number < 1) throw new IllegalArgumentException();
int n = number;
int counter = 1;
while (n / 10 >= 1){
counter ++;
n = n / 10;
}
return counter;
}
You need to copy the number which you use to find out how much digits your number has. Otherwise you change the number itself and don't know anymore what it was.
The second mistake is that you divide an integer by Math.pow() which returns a double. So your result is double. You want to have an integer to use the modulo operator.
public static boolean isFriendly(int number)
{
int counter = 1;
int tmpNumber = number;
while (tmpNumber / 10 >= 1)
{
counter ++;
tmpNumber = tmpNumber / 10;
}
boolean check = true;
for (int i = 1; i <= counter; i++)
{
if ((int)(number / Math.pow(10, (counter - i))) % i == 0 && check)
{
check = true;
}
else
{
check = false;
}
}
return check;
}
The first problem is that you are modifying the value of the number you are trying to check. So, if your method is called with 149, then after the while loop to count the digits, its value will be 1. So, you are always going to find that it is 'unfriendly'. Assuming you fix this so that number contains the number you are checking. Try this instead of your 'for' loop:
while ( counter && !( ( number % 10 / counter ) % counter ) )
{
number = number / 10;
counter--;
}
It works by taking the last digit of your number using the modulus or remainder operator and then divides this by the digit position and checks that the remainder is zero. If all is good, it decrements the counter until it reaches zero, otherwise it terminates before counter is zero.
Try something like this (change your isFriendly() method):
public static boolean isFriendly(int number)
{
String numberAsString = String.valueOf(number); //Convert the int as a String to make it easier to iterate through
for(int i = 0; i < numberAsString.length(); i++) {
int currentDigit = Character.getNumericValue(numberAsString.charAt(numberAsString.length() - i - 1)); //Iterate over the number backwards
System.out.println(currentDigit); //Print the current digit
if(currentDigit % (i + 1) != 0) {
return false;
}
}
return true;
}
The easy way is to convert to string and then check if it is friendly:
public static boolean isFriendly(int number)
{
String num = Integer.toString(number);
for (int i = 0, dividedBy = 1; i < num.length(); i++, dividedBy++)
{
String numToCheck = "";
for (int j = 0; j <= i; j++)
{
numToCheck += num.charAt(j);
}
if (Integer.valueOf(numToCheck) % dividedBy != 0) {
return false;
}
}
return true;
}
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
}
}
}
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.
In the output, I get a 9 where I should be getting an 11!
This occurs after the fifth call to nextPrime(). Every other output is correct except for the 5th one! I have been struggling to determine my error for a few hours now. Sorry if my code is sloppy, this is the way my mind figured out the problem! It was a requirement to use the flag controlled loop.
public class PrimeGenerator
{
private int num = 2;
public PrimeGenerator()
{
}
public int nextPrime()
{
boolean done = false;
for (int n = num; !isPrime(num); n++)
num = n;
if (isPrime(num))
{
done = true;
}
if (done)
{
int prime = num;
num++;
return prime;
}
return num;
}
public static boolean isPrime(int n)
{
boolean result = true;
for (int i = 2; n % i == 0 && i < n; i++)
result = false;
if (n == 2)
result = true;
return result;
}
}
My Tester just calls the nextPrime() method and prints the result.
You get 9 instead of 11 because you have mistake in method isPrime
public static boolean isPrime(int n)
{
boolean result = true;
for (int i = 2; n % i == 0 && i < n; i++)
result = false;
if (n == 2)
result = true;
return result;
}
Look for number 9.
first iteration: i = 2, result = true
n % i => 9 % 2 = 1, so your loop stops before first iteration and result didn't changed.
Try to change method isPrime (Updated as commented #John in comments)
public static boolean isPrime(int n)
{
if( n % 2 == 0 ) {
return false;
}
double root = Math.sqrt(n);
for ( int i = 3; i < root; i+=2 ) {
if( n % i == 0 ) {
return false;
}
}
return true;
}
Your nextPrime method returns num whether or not it is prime. Your code is effectively:
if(isPrime(num))
return num;
}
return num;
So the main problem with your code here is the method for checking if a number is prime. According to number theory, you just need to check that the given number is not divisible by any number between 2 and the root of the given number you want to determine is prime. More formally, if you want to check if a number n is prime, you need to check that n is not divisible by any number between 2 and sqrt(n).
An updated method using this number theory fact is below:
public static boolean isPrime(int n)
{
int root = (int)Math.sqrt(n);
for (int i = 2; i <= root; i++) {
if(n % i == 0) {
return false;
}
}
return true;
}
With this your determination of the prime number would be correct and would be much faster. There are even faster ways of determining primes and generating primes like sieve's algorithm.