This was asked during my interview. I have to write a program to find all the prime numbers which are having only odd digits in them for the given range.
Eg: 31 is a prime number having only odd digits in it 3 & 1.
Eg: 23 is a prime number but it is not having odd digits in it, because it has digit 2.
Now I have one more constraint, to my program, I will pass a variable called temp.
Now if this temp is 1 then I should find the primes, with digits containing only <= 5.
If this temp is 2 then I should find the primes, with digits containing only >= 5.
Sample Input:
If the start position is 30 & end position is 40 with temp value as 1. The possible prime numbers are 31, 37 in the 30 to 40.
31 prime has digits 3 & 1 => so these digits are <= 5.
Now if my temp input data is `1` then the program should return me 1.
If suppose my temp input data is `2` then the program should return me 0.
37 is a prime number with digits 3 & 7. Here 3 <=5 and 7 >= 5. So we should not count this prime number as it will not fall under any category defined for my temp variable.
So for input values start=30, end = 40, temp = 1 output should be 1.
(because of prime number 31).
I have come up with the below code:
public static int process(int start, int end, int temp) {
List<Integer> matching = new ArrayList<>();
// loop from start to end
for (int i = start; i <= end; i++) {
// 0 & 1 are not primes so skip them
if (i == 1 || i == 0) {
continue;
}
// Check if the number is a prime
if (isPrime(i)) {
// Get the digits of that prime number Eg: 31 has digits 3 & 1
List<Integer> nums = new ArrayList<>();
buildDigits(i, nums);
// Codition to check if we need to consider this prime or not in our result.
boolean flag = true;
for (Integer num : nums) {
// The prime number is has an even digit, so discard it.
if (num % 2 == 0) {
flag = false;
break;
}
// The prime has a digit > 5 where as the restriction falls under step 1, so discard
if (temp == 1 && num > 5) {
flag = false;
}
// The prime has a digit < 5 where as the restriction falls under step 2, so discard
if (temp == 2 && num < 5) {
flag = false;
}
}
// Get the required primes
if (flag) {
matching.add(i);
}
}
}
// Return their count
return matching.size();
}
// Find out all digits in a given number, and put them in the list called nums
public static void buildDigits(int num, List<Integer> nums) {
if (num / 10 > 0) {
buildDigits(num / 10, nums);
}
nums.add(num % 10);
}
// This just finds out if the given input is prime or not
public static boolean isPrime(int n) {
if (n <= 1) {
return false;
}
if (n <= 3) {
return true;
}
if (n % 2 == 0 || n % 3 == 0) {
return false;
}
for (int i = 5; i * i <= n; i = i + 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
return true;
}
I above code, I have used this link as basis for isPrime to find prime or not.
When I used this code in my interview it cleared only 3 test cases out of 8. The test cases are hidden, I was not clear for what inputs this logic failed.
I have gone through this code in debug mode also, but I was not able to find where I made mistake.
Related
This is the code I know:
bool checkPrime(int n) {
bool prime = true;
for (int i = 2; i < n; i++) {
if ((n%i) == 0) {
prime = false;
}
}
return prime;
}
But is this ok if you’re looking for prime numbers:
List<int> arr = [2, 3, 5, 7]; // Already known
int n = 30; // Between 1 to 30. It could be any number
for (int i = 2; i < n; i++) {
if (i % 2 != 0 && i % 3 != 0 && i % 5 != 0 && i % 7 != 0) {
arr.add(i);
}
// Then maybe some code for numbers less than 8
}
print(arr);
Output:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
And also is there much difference in time complexity?
Your code is incorrect.
This code only works because you are taking the value of n as 30, for a greater number like 1000 this will produce an incorrect result.
List arr = [2,3,5,7]; // already known
int n = 1000; // between 1 to 1000 it could be any number
List<int> arr = [2,3,5,7];
for (int i = 2; i < n; i++) {
if (i % 2 != 0 && i % 3 != 0 && i % 5 != 0 && i % 7 != 0){
arr.add(i);
}
//Then maybe some code for numbers less than 8
}
print(arr);
Your code will return 231 prime numbers when there are actually only 168 prime numbers.
This is because you are not considering the future prime numbers that can only be divided by a prime number between 7 to that number.
eg: 121 will be returned by you as prime but it is a multiple of 11
Extending your pattern.
Though this will be faster since it has reduced a number of division operations but due to two loops, it will still be N square.
Here I am simply only dividing numbers from the existing prime numbers collection and adding them in the collection if prime is found tobe used in next iteration for division.
List < int > arr = [2]; // taking 2 since this is the lowerst value we want to start with
int n = 30; // n can between 2 to any number
if (n < 3) {
print(arr); // can return from here.
}
// since we already have added 2 in the list we start with next number to check that is 3
for (int i = 3; i < n; i++) {
bool isPrime = true;
for (int j = 0; j < arr.length; j++) { // we iterate over the current prime number collection only [2] then [2,3]...
if (i % arr[j] == 0) { // check if number can be divided by exisiting numbers
isPrime = false;
}
}
if (isPrime) { // eg: 2 cant divide 3 so we 3 is also added
arr.add(i)
}
}
print(arr);
You can look a faster pattern here.
Which is the fastest algorithm to find prime numbers?
I am trying to find the Largest prime factor of a number while solving this problem here. I think that I am doing everything right, however one of the test case (#2) is failing and I can't think of any corner case where it might fail. Here's my code, please have a look and try to spot something.
public class ProblemThree
{
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
int T = scanner.nextInt();
for (int i = 0; i < T; i++)
{
System.out.println(largestPrime(scanner.nextLong()));
}
}
private static long largestPrime(long n)
{
while (n % 2 == 0)
{
n = n / 2; // remove all the multiples of 2
}
while (n % 3 == 0)
{
n = n / 3; // remove all the multiples of 2
}
// remove multiples of prime numbers other than 2 and 3
while (n >= 5)
{
boolean isDivisionComplete = true;
for (long i = 5; i < Math.ceil(Math.sqrt(n)); i++)
{
if (n % i == 0)
{
n = n / i;
isDivisionComplete = false;
break;
}
}
if (isDivisionComplete)
{
break;
}
}
return n;
}
}
Basically, what I am doing is:
Largest_Prime(n):
1. Repeatedly divide the no by any small number, say x where 0 < x < sqrt(n).
2. Then set n = n/x and repeat steps 1 and 2 until there is no such x that divides n.
3 Return n.
It seems you have some bug in your code as as when you input 16 largestPrime function return 1. and this is true for when input is the power of 3.
Detailed Algorithm description:
You can do this by keeping three variables:
The number you are trying to factor (A)
A current divisor store (B)
A largest divisor store (C)
Initially, let (A) be the number you are interested in - in this case, it is 600851475143. Then let (B) be 2. Have a conditional that checks if (A) is divisible by (B). If it is divisible, divide (A) by (B), reset (B) to 2, and go back to checking if (A) is divisible by (B). Else, if (A) is not divisible by (B), increment (B) by +1 and then check if (A) is divisible by (B). Run the loop until (A) is 1. The (3) you return will be the largest prime divisor of 600851475143.
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for(int a0 = 0; a0 < t; a0++){
long n = in.nextLong();
long A=n;
long B=2;
long C=0;
while(Math.pow(B,2)<=A)
{
if(A%B==0)
{
C=B;
A=A/B;
B=2;
}
else
B++;
}
if(A>=C)
C=A;
if(A==1)
{ C=2;
break;
}
System.out.println(C);
}
}
Why are you removing multiples of 2 and multiples of 3? This way if you have a number that is any combination of powers of 2 and 3 you will get your answer as 1 which is clearly wrong.
For this problem you can do the naive way of looping from 2 to sqrt(n) and store the largest number which divides n, when you finish your loop just return the highest divisor you found.
1 drop your loop for 2 and 3. If not, you dont get 2, 2x2, 3, 2x3, ... all multiples of 2 and 3
2 change your loop to stop at 2 (and not 5):
while (n >= 2)
{
3 stop if 2
if (n==2) return 2;
4 loop from 2
and
5 loop until sqrt(n), with <= and not only < (if not, you dont get prime X Prime)
for (long i = 2; i <= Math.ceil(Math.sqrt(n)); i++)
One easy way of extracting prime factors is like this:
/**
* Prime factors of the number - not the most efficient but it works.
*
* #param n - The number to factorise.
* #param unique - Want only unique factors.
* #return - List of all prime factors of n.
*/
public static List<Long> primeFactors(long n, boolean unique) {
Collection<Long> factors;
if (unique) {
factors = new HashSet<>();
} else {
factors = new ArrayList<>();
}
for (long i = 2; i <= n / i; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
}
if (n > 1) {
factors.add(n);
}
return new ArrayList<>(factors);
}
Those first loops are a problem. They will reduce all even numbers to 1 - thus missing 2 as the factor. Changing your code to use:
while (n > 2 && n % 2 == 0) {
n = n / 2; // remove all the multiples of 2
}
while (n > 3 && n % 3 == 0) {
n = n / 3; // remove all the multiples of 2
}
You still have further issues - e.g. you report the largest prime factor of 25 to be 25 and the largest prime factor of 49 to be 49.
Just run this code using yours and mine to see where yours fails:
for (long i = 1; i < 1000; i++) {
long largestPrime = largestPrime(i);
List<Long> primeFactors = primeFactors(i, true);
if (primeFactors.size() > 0) {
Collections.sort(primeFactors, Collections.reverseOrder());
long highestFactor = primeFactors.get(0);
if (largestPrime != highestFactor) {
System.out.println("Wrong! " + i + " " + largestPrime + " != " + primeFactors);
}
} else {
System.out.println("No factors for " + i);
}
}
In my current Project Euler problem 5, I have a "working" solution. It works on smaller numbers (the example one in the question), but not on the actual problem, because I'm brute forcing it, and the program doesn't finish.
Here's the explanation of the problem:
2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible1 by all of the numbers from 1 to 20?
1: Divisible with no remainder
Here is my current code:
package Euler;
public class Euler5 {
public static void main(String[] args) {
int desiredNumber = 20;
boolean exitLoop = false;
long counter = 1;
while(exitLoop == false) {
long loopCounter = 0;
for(int i=1; i<=desiredNumber; i++) {
if(counter % i == 0) {
loopCounter++;
}
}
if(loopCounter == desiredNumber) {
exitLoop = true;
System.out.println(counter);
}
counter++;
}
}
}
You don't have a computer to answer this question. Look: if a number can be divided by each of the numbers from 1 to 20 it means that it should be a multiplication of primes in corresponding powers:
2**4 (from 16)
3**2 (from 9)
5
7
11
13
17
19
so the solution is
16 * 9 * 5 * 7 * 11 * 13 * 17 * 19 == 232792560
since the answer is quite large I doubt if brute force is a reasonable method here.
In general case (for some n >= 2) find out all the prime numbers that are not exeeding the n:
2, 3, ..., m (m <= n)
then, for each prime number a find out the power pa such that
a**pa <= n
but
a**(pa + 1) > n
the answer will be
2**p2 * 3**p3 * ... * m**pm
Possible Java implementation:
public static BigInteger evenlyDivisible(int n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
else if (n <= 2)
return BigInteger.valueOf(n);
ArrayList<Integer> primes = new ArrayList<Integer>();
primes.add(2);
for (int i = 3; i <= n; i += 2) {
boolean isPrime = true;
for (int p : primes) {
if (i % p == 0) {
isPrime = false;
break;
}
else if (p * p > i)
break;
}
if (isPrime)
primes.add(i);
}
BigInteger result = BigInteger.ONE;
for(int p : primes) {
// Simplest implemenation, check for round up errors however
int power = (int)(Math.log(n) / Math.log(p));
result = result.multiply(BigInteger.valueOf(p).pow(power));
}
return result;
}
...
System.out.println(evenlyDivisible(20)); // 232792560
The number you are seeking is the Least common multiple (LCM) of the numbers 1,2,3,...,20.
By splitting each numbers to the multiplication of its prime factors (easy for small numbers), finding LCM is fairly easy.
I am trying to figure out how this Java method calculates a prime number but something is confusing me.
public static boolean isPrime(int number){
for(int divisor =2; divisor <= number / 2; divisor++){
if (number % divisor ==0){
return false;
}
}
return true;
}
As you see in the second line in the for loop it shows divisor <= number /2 instead of divisor <= number. Can anyone tell me the reason for that?
First, if you put divisor <= number, you would get no prime numbers at all, because every number is divisible by itself. If the loop does not exit before divisor becomes number, you would get to
number % divisor == 0
condition, and return false.
Whoever wrote this code made an observation that you can stop as soon as you have reached half the number, because if you did not find divisors in the lower half of the interval (2..number/2), there would be no divisors above half the number either, so you can declare the number prime without trying, unsuccessfully, the rest of the candidate divisors.
However, this is not the best you can do: a stronger condition can be used - you could compare divisor to square root of number. This works, because if you don't have a divisor that is less than or equal to the square root of number, there would be no divisors above the square root as well (it is a good idea to think why this is so).
int stop = Math.sqrt(number);
for(int divisor = 2; divisor <= stop ; divisor++) {
...
}
The reason is is that any number can't be divided by any divisor larger than it's half and give more than 1 (if we are talking integers, of course).
Any number would not be divisible by a number more than its half.
For example, the last number 10 would be divisible is 5. 10 is not divisible with 6, 7, 8 or 9.
This is why it's good to eliminate the obvious mismatches to improve the performance of the algorithm.
As others have noted, there are no factors of n greater than n/2. A better solution is comparing your iterating variable to the square root of n, as if there are no factors less than or equal to the square root, there can't be any greater than the square root (Note that it is more efficient to compare i*i <= n that i <= Math.sqrt(n)).
An even better approach is the AKS primality test. If the number is 2 or 3, then it obviously must be prime. Otherwise, it can be rewritten in the form (6k+i) where i = -1, 0, 1, 2, 3, 4. Any (6k + 2) or (6k + 4) is divisible by 2, and any (6k + 3) is divisible by three, so the prime numbers must either take the form (6k - 1) or (6k + 1).
public static boolean isPrime(long n) {
/* This code uses the AKS primality test
* http://en.wikipedia.org/wiki/AKS_primality_test
*/
if (n <= 3) return n > 1;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i*i <=n; i+=6) {
if (n % i == 0 || n % (i+2) == 0) return false;
}
return true;
}
}
I used this as a part of my solution to the PrimeCounter problem in Sedgewick's Intro to Programming in Java (although this is in the first chapter before methods are introduced).
public class PrimeCounter {
public static void main(String[] args) {
long n = 10000000;
long count = 0;
for (long i = 0; i <= n; i++) {
if (isPrime(i)) count++;
}
System.out.println("The number of primes less than "
+ n + " is " + count);
}
public static boolean isPrime(long n) {
/* This code uses the AKS primality test
* http://en.wikipedia.org/wiki/AKS_primality_test
*/
if (n <= 3) return n > 1;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i*i <=n; i+=6) {
if (n % i == 0 || n % (i+2) == 0) return false;
}
return true;
}
}
It's using the fact that if one of the factors is greater than N/2 the other must be smaller than 2.
In fact a massive (asymptotic) gain can be obtained by using the square-root.
That's because if one factor is greater than the square root the other is less.
Sorry Sebri Zouhaier. I'm changing allegiance.
The +1 isn't necessary so the best answer is below.
I'm sorry to change sides for such a tiny improvement!
A number N cannot have any divisors D that are > N/2 and < N. To see this, note that if D is a divisor of N, then it must equal N/D2 for some D2. So the divisors of N are those values of this sequence that are integers: N, N/2, N/3, ... This is a descending sequence. It should be obvious that there can't be any divisors between N and N/2.
In fact, it's common for programs that check for primality to stop at sqrt(N) instead of N/2. The reason is this: Suppose there's a divisor D such that D > sqrt(N). Then N/D = D2 also must be a divisor of N. And it must be the case that D2 < sqrt(N), because if both D and D2 were > sqrt(N), then D * D2 would have to be > N, which is wrong because D * D2 = N. This means that there is no need to check possible divisors D > sqrt(N); if such a divisor existed, we already would have found D2 earlier in the loop and proven that N was not prime.
One small caveat to some of the above answers is that 0 and 1 are not prime numbers. You could account for this (for positive integers) with an implementation such as
public static boolean isPrime(int number){
if (number == 0 || number == 1)
return false;
else
{
int stop = (int) Math.sqrt(number);
for (int divisor = 2; divisor <= stop ; divisor++)
{
if (number % divisor ==0)
return false;
}
return true;
}
}
public static Boolean isPrime(int num){ //method signature. returns Boolean, true if number isPrime, false if not
if(num==2){ //for case num=2, function returns true. detailed explanation underneath
return(true);
}
for(int i=2;i<=(int)Math.sqrt(num)+1;i++){ //loops through 2 to sqrt(num). All you need to check- efficient
if(num%i==0){ //if a divisor is found, its not prime. returns false
return(false);
}
}
return(true); //if all cases don't divide num, it is prime.
}
// Returns true iff n is prime. First checks if n is even, handling the
// cases of n=2 (prime) or n is even > 2 (not prime). Then checks if any
// odd #'s between 3 and sqrt(n), inclusive, are divisors of n, returning
// false if any are.
public static boolean isPrime(int n) {
if (n < 2) return false;
if (n % 2 == 0)
// n is an even, so return true iff n is exactly 2
return (n == 2);
for (int i=3; i*i<=n; i+=2)
if (n % i == 0)
// i divides evenly into n, so n is not prime
return false;
return true;
}
I am working on a prime factorization program implemented in Java.
The goal is to find the largest prime factor of 600851475143 (Project Euler problem 3).
I think I have most of it done, but I am getting a few errors.
Also my logic seems to be off, in particular the method that I have set up for checking to see if a number is prime.
public class PrimeFactor {
public static void main(String[] args) {
int count = 0;
for (int i = 0; i < Math.sqrt(600851475143L); i++) {
if (Prime(i) && i % Math.sqrt(600851475143L) == 0) {
count = i;
System.out.println(count);
}
}
}
public static boolean Prime(int n) {
boolean isPrime = false;
// A number is prime iff it is divisible by 1 and itself only
if (n % n == 0 && n % 1 == 0) {
isPrime = true;
}
return isPrime;
}
}
Edit
public class PrimeFactor {
public static void main(String[] args) {
for (int i = 2; i <= 600851475143L; i++) {
if (isPrime(i) == true) {
System.out.println(i);
}
}
}
public static boolean isPrime(int number) {
if (number == 1) return false;
if (number == 2) return true;
if (number % 2 == 0) return false;
for (int i = 3; i <= number; i++) {
if (number % i == 0) return false;
}
return true;
}
}
Why make it so complicated? You don't need do anything like isPrime(). Divide it's least divisor(prime) and do the loop from this prime. Here is my simple code :
public class PrimeFactor {
public static int largestPrimeFactor(long number) {
int i;
for (i = 2; i <= number; i++) {
if (number % i == 0) {
number /= i;
i--;
}
}
return i;
}
/**
* #param args
*/
public static void main(String[] args) {
System.out.println(largestPrimeFactor(13195));
System.out.println(largestPrimeFactor(600851475143L));
}
}
edit: I hope this doesn't sound incredibly condescending as an answer. I just really wanted to illustrate that from the computer's point of view, you have to check all possible numbers that could be factors of X to make sure it's prime. Computers don't know that it's composite just by looking at it, so you have to iterate
Example: Is X a prime number?
For the case where X = 67:
How do you check this?
I divide it by 2... it has a remainder of 1 (this also tells us that 67 is an odd number)
I divide it by 3... it has a remainder of 1
I divide it by 4... it has a remainder of 3
I divide it by 5... it has a remainder of 2
I divide it by 6... it has a remainder of 1
In fact, you will only get a remainder of 0 if the number is not prime.
Do you have to check every single number less than X to make sure it's prime? Nope. Not anymore, thanks to math (!)
Let's look at a smaller number, like 16.
16 is not prime.
why? because
2*8 = 16
4*4 = 16
So 16 is divisible evenly by more than just 1 and itself. (Although "1" is technically not a prime number, but that's technicalities, and I digress)
So we divide 16 by 1... of course this works, this works for every number
Divide 16 by 2... we get a remainder of 0 (8*2)
Divide 16 by 3... we get a remainder of 1
Divide 16 by 4... we get a remainder of 0 (4*4)
Divide 16 by 5... we get a remainder of 1
Divide 16 by 6... we get a remainder of 4
Divide 16 by 7... we get a remainder of 2
Divide 16 by 8... we get a remainder of 0 (8*2)
We really only need one remainder of 0 to tell us it's composite (the opposite of "prime" is "composite").
Checking if 16 is divisible by 2 is the same thing as checking if it's divisible by 8, because 2 and 8 multiply to give you 16.
We only need to check a portion of the spectrum (from 2 up to the square-root of X) because the largest number that we can multiply is sqrt(X), otherwise we are using the smaller numbers to get redundant answers.
Is 17 prime?
17 % 2 = 1
17 % 3 = 2
17 % 4 = 1 <--| approximately the square root of 17 [4.123...]
17 % 5 = 2 <--|
17 % 6 = 5
17 % 7 = 3
The results after sqrt(X), like 17 % 7 and so on, are redundant because they must necessarily multiply with something smaller than the sqrt(X) to yield X.
That is,
A * B = X
if A and B are both greater than sqrt(X) then
A*B will yield a number that is greater than X.
Thus, one of either A or B must be smaller than sqrt(X), and it is redundant to check both of these values since you only need to know if one of them divides X evenly (the even division gives you the other value as an answer)
I hope that helps.
edit: There are more sophisticated methods of checking primality and Java has a built-in "this number is probably prime" or "this number is definitely composite" method in the BigInteger class as I recently learned via another SO answer :]
You need to do some research on algorithms for factorizing large numbers; this wikipedia page looks like a good place to start. In the first paragraph, it states:
When the numbers are very large, no efficient integer factorization algorithm is publicly known ...
but it does list a number of special and general purpose algorithms. You need to pick one that will work well enough to deal with 12 decimal digit numbers. These numbers are too large for the most naive approach to work, but small enough that (for example) an approach based on enumerating the prime numbers starting from 2 would work. (Hint - start with the Sieve of Erasthones)
Here is very elegant answer - which uses brute force (not some fancy algorithm) but in a smart way - by lowering the limit as we find primes and devide composite by those primes...
It also prints only the primes - and just the primes, and if one prime is more then once in the product - it will print it as many times as that prime is in the product.
public class Factorization {
public static void main(String[] args) {
long composite = 600851475143L;
int limit = (int)Math.sqrt(composite)+1;
for (int i=3; i<limit; i+=2)
{
if (composite%i==0)
{
System.out.println(i);
composite = composite/i;
limit = (int)Math.sqrt(composite)+1;
i-=2; //this is so it could check same prime again
}
}
System.out.println(composite);
}
}
You want to iterate from 2 -> n-1 and make sure that n % i != 0. That's the most naive way to check for primality. As explained above, this is very very slow if the number is large.
To find factors, you want something like:
long limit = sqrt(number);
for (long i=3; i<limit; i+=2)
if (number % i == 0)
print "factor = " , i;
In this case, the factors are all small enough (<7000) that finding them should take well under a second, even with naive code like this. Also note that this particular number has other, smaller, prime factors. For a brute force search like this, you can save a little work by dividing out the smaller factors as you find them, and then do a prime factorization of the smaller number that results. This has the advantage of only giving prime factors. Otherwise, you'll also get composite factors (e.g., this number has four prime factors, so the first method will print out not only the prime factors, but the products of various combinations of those prime factors).
If you want to optimize that a bit, you can use the sieve of Eratosthenes to find the prime numbers up to the square root, and then only attempt division by primes. In this case, the square root is ~775'000, and you only need one bit per number to signify whether it's prime. You also (normally) only want to store odd numbers (since you know immediately that all even numbers but two are composite), so you need ~775'000/2 bits = ~47 Kilobytes.
In this case, that has little real payoff though -- even a completely naive algorithm will appear to produce results instantly.
I think you're confused because there is no iff [if-and-only-if] operator.
Going to the square root of the integer in question is a good shortcut. All that remains is checking if the number within that loop divides evenly. That's simply [big number] % i == 0. There is no reason for your Prime function.
Since you are looking for the largest divisor, another trick would be to start from the highest integer less than the square root and go i--.
Like others have said, ultimately, this is brutally slow.
private static boolean isPrime(int k) throws IllegalArgumentException
{
int j;
if (k < 2) throw new IllegalArgumentException("All prime numbers are greater than 1.");
else {
for (j = 2; j < k; j++) {
if (k % j == 0) return false;
}
}
return true;
}
public static void primeFactorsOf(int n) {
boolean found = false;
if (isPrime(n) == true) System.out.print(n + " ");
else {
int i = 2;
while (found == false) {
if ((n % i == 0) && (isPrime(i))) {
System.out.print(i + ", ");
found = true;
} else i++;
}
primeFactorsOf(n / i);
}
}
For those answers which use a method isPrime(int) : boolean, there is a faster algorithm than the one previously implemented (which is something like)
private static boolean isPrime(long n) { //when n >= 2
for (int k = 2; k < n; k++)
if (n % k == 0) return false;
return true;
}
and it is this:
private static boolean isPrime(long n) { //when n >= 2
if (n == 2 || n == 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int k = 1; k <= (Math.floor(Math.sqrt(n)) + 1) / 6; k++)
if (n % (6 * k + 1) == 0 || n % (6 * k - 1) == 0) return false;
return true;
}
I made this algorithm using two facts:
We only need to check for n % k == 0 up to k <= Math.sqrt(n). This is true because for anything higher, factors merely "flip" ex. consider the case n = 15, where 3 * 5 = 5 * 3, and 5 > Math.sqrt(15). There is no need for this overlap of checking both 15 % 3 == 0 and 15 % 5 == 0, when we could just check one of these expressions.
All primes (excluding 2 and 3) can be expressed in the form (6 * k) + 1 or (6 * k) - 1, because any positive integer can be expressed in the form (6 * k) + n, where n = -1, 0, 1, 2, 3, or 4 and k is an integer <= 0, and the cases where n = 0, 2, 3, and 4 are all reducible.
Therefore, n is prime if it is not divisible by 2, 3, or some integer of the form 6k ± 1 <= Math.sqrt(n). Hence the above algorithm.
--
Wikipedia article on testing for primality
--
Edit: Thought I might as well post my full solution (*I did not use isPrime(), and my solution is nearly identical to the top answer, but I thought I should answer the actual question):
public class Euler3 {
public static void main(String[] args) {
long[] nums = {13195, 600851475143L};
for (num : nums)
System.out.println("Largest prime factor of " + num + ": " + lpf(num));
}
private static lpf(long n) {
long largestPrimeFactor = 1;
long maxPossibleFactor = n / 2;
for (long i = 2; i <= maxPossibleFactor; i++)
if (n % i == 0) {
n /= i;
largestPrimeFactor = i;
i--;
}
return largestPrimeFactor;
}
}
To find all prime factorization
import java.math.BigInteger;
import java.util.Scanner;
public class BigIntegerTest {
public static void main(String[] args) {
BigInteger myBigInteger = new BigInteger("65328734260653234260");//653234254
BigInteger originalBigInteger;
BigInteger oneAddedOriginalBigInteger;
originalBigInteger=myBigInteger;
oneAddedOriginalBigInteger=originalBigInteger.add(BigInteger.ONE);
BigInteger index;
BigInteger countBig;
for (index=new BigInteger("2"); index.compareTo(myBigInteger.add(BigInteger.ONE)) <0; index = index.add(BigInteger.ONE)){
countBig=BigInteger.ZERO;
while(myBigInteger.remainder(index) == BigInteger.ZERO ){
myBigInteger=myBigInteger.divide(index);
countBig=countBig.add(BigInteger.ONE);
}
if(countBig.equals(BigInteger.ZERO)) continue;
System.out.println(index+ "**" + countBig);
}
System.out.println("Program is ended!");
}
}
I got a very similar problem for my programming class. In my class it had to calculate for an inputted number. I used a solution very similar to Stijak. I edited my code to do the number from this problem instead of using an input.
Some differences from Stijak's code are these:
I considered even numbers in my code.
My code only prints the largest prime factor, not all factors.
I don't recalculate the factorLimit until I have divided all instances of the current factor off.
I had all the variables declared as long because I wanted the flexibility of using it for very large values of number. I found the worst case scenario was a very large prime number like 9223372036854775783, or a very large number with a prime number square root like 9223371994482243049. The more factors a number has the faster the algorithm runs. Therefore, the best case scenario would be numbers like 4611686018427387904 (2^62) or 6917529027641081856 (3*2^61) because both have 62 factors.
public class LargestPrimeFactor
{
public static void main (String[] args){
long number=600851475143L, factoredNumber=number, factor, factorLimit, maxPrimeFactor;
while(factoredNumber%2==0)
factoredNumber/=2;
factorLimit=(long)Math.sqrt(factoredNumber);
for(factor=3;factor<=factorLimit;factor+=2){
if(factoredNumber%factor==0){
do factoredNumber/=factor;
while(factoredNumber%factor==0);
factorLimit=(long)Math.sqrt(factoredNumber);
}
}
if(factoredNumber==1)
if(factor==3)
maxPrimeFactor=2;
else
maxPrimeFactor=factor-2;
else
maxPrimeFactor=factoredNumber;
if(maxPrimeFactor==number)
System.out.println("Number is prime.");
else
System.out.println("The largest prime factor is "+maxPrimeFactor);
}
}
public class Prime
{
int i;
public Prime( )
{
i = 2;
}
public boolean isPrime( int test )
{
int k;
if( test < 2 )
return false;
else if( test == 2 )
return true;
else if( ( test > 2 ) && ( test % 2 == 0 ) )
return false;
else
{
for( k = 3; k < ( test/2 ); k += 2 )
{
if( test % k == 0 )
return false;
}
}
return true;
}
public void primeFactors( int factorize )
{
if( isPrime( factorize ) )
{
System.out.println( factorize );
i = 2;
}
else
{
if( isPrime( i ) && ( factorize % i == 0 ) )
{
System.out.print( i+", " );
primeFactors( factorize / i );
}
else
{
i++;
primeFactors( factorize );
}
}
public static void main( String[ ] args )
{
Prime p = new Prime( );
p.primeFactors( 649 );
p.primeFactors( 144 );
p.primeFactors( 1001 );
}
}