Tips to solve problem #41 of project euler - java

I'm trying to solve Problem 41of project Euler in Java, by counting the number from 99888888 to 80000000(which took very long time :( ), I got 98765431 as an answer, but I'm getting that answer not correct. Could anyone please tell me the reason of not getting the correct answer and how can I speed my program?

A pandigital number doesn't needs to contain all numbers from 1 to 9, but all from 1 to length.
So, you'll need to try all permutations from 1 to 9 starting with 1 digit and going up, filtering all prime numbers and, then, taking largest one.

The only possible prime pandigital numbers are those with length 1, 4, & 7 because every other pandigital number has the sum of its digits divisible by 3.
So, you'd only need to test for 7! = 5040 permutations.

To obtain a solution in a "reasonable" time, you need the following observations based on the special property that a number is divisible by 3 if the sum of its digits is divisible by 3:
divisible by
1+2+3+4 = 10 -
1+2+3+4+5 = 15 3
1+2+3+4+5+6 = 21 3
1+2+3+4+5+6+7 = 28 -
1+2+3+4+5+6+7+8 = 36 3
1+2+3+4+5+6+7+8+9 = 45 3
So, a "big" prime pandigital number has 4 or 7 digits. (a prime number bigger than 3 is not divisible by 3)
Because you want to obtain the biggest number, it's better to start with the 7-digit numbers and continue to check the 4-digit numbers only if the number was not found. For sure, a 4-digit number exists, because it is specified: 2143.
Now, a possible solution looks like this:
public class P41 {
public static void main(String[] args) {
boolean wasFound = false;
for (int nr = 7654321; nr >= 1234567; nr -= 2) { // even != prime
if (isPandigital(nr) && isOddPrime(nr)) {
System.out.println(nr);
wasFound = true;
break;
}
}
if (!wasFound) {
/* not <=, because 1234 is even */
for (int nr = 4321; nr > 1234; nr -= 2) {
if (isPandigital(nr) && isOddPrime(nr)) {
System.out.println(nr);
break;
}
}
}
}
private static boolean isOddPrime(int x) {
int sqrt = (int) Math.sqrt(x);
for (int i = 3; i <= sqrt; i += 2) {
if (x % i == 0) {
return false;
}
}
return true;
}
private static int getNumberOfDigits(int x) {
int count = 0;
while (x > 0) {
count++;
x /= 10;
}
return count;
}
private static boolean isPandigital(int x) {
int numberOfDigits = getNumberOfDigits(x);
Set<Integer> digits = new HashSet<Integer>();
for (int i = 1; i <= numberOfDigits; i++) {
digits.add(i);
}
for (int i = 1; i <= numberOfDigits; i++) {
digits.remove(x % 10);
x /= 10;
}
if (digits.size() == 0) {
return true;
} else {
return false;
}
}
}
Time: 8 ms.

Here is the problem statement:
We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once. For example, 2143 is a 4-digit pandigital and is also prime. What is the largest n-digit pandigital prime that exists?
I wrote a program that started with 987654321 and counted down. I checked that the number was pandigital, and if it was, checked if it was prime.
It took 66 seconds on my Windows 8.1 computer to find the largest prime pandigital.
When I tested the other way around, first prime, then pandigital, the program took way longer than 66 seconds. I cancelled it.
When I applied GregS' tip about discounting all 9 digit and 8 digit pandigital numbers, and started counting down from 7654321, my brute force algorithm took 13 milliseconds.

Related

How to calculate prime fibonacci numbers?

(This is an extension from my previous question).
How to print a text notification beside prime fibonacci numbers?
Task:
The section of the assignment I am having difficulty with reads as follows:
Determine which of the first 20 Fibonacci numbers are prime numbers.
Put a “this is a prime” text notification in the printout from the Basic challenge.
Store the FibPrimes in an array called FibPrimes.
Problem:
I cannot seem to figure out how to take each individual fibonacci number, determine it is prime, put the prime fibonacci numbers in an array, and print the output. I was able to make a working program previously, but I didn't use code to calculate the primes, I manually entered them into an array (see previous attempt at bottom).
Attempt:
Here is what I have attempted:
The code that is relevant to this question is emphasized with comments.
package fibonaccinumbers;
public class FibonacciNumbers {
public static void main(String[] args) {
// Creation of Fibonacci Numbers Array.
// Let i represent the index number.
int [] FibNums = new int[20];
FibNums[0] = 0;
FibNums[1] = 1;
// Will add on each successive FibNums.
// Will be used to calculate average.
int FibSum = 1;
// RELEVANT TO QUESTION.
// Creation if Fibonacci Primes Array.
// Let n represent the index number.
int [] FibPrimes = new int[7];
int n=0;
// Printing first two fibonacci numbers.
System.out.println(0);
System.out.println(1 + "*");
// Printing remaining fibonacci numbers up to 20th term.
for (int i=2; i<FibNums.length;i++){ // Begin number generation loop.
FibNums[i] = FibNums[i-1] + FibNums[i-2];
// Checks if the fibonacci number is odd.
// A number is not odd if two divides into it evenly.
boolean oddcheck = true;
if (FibNums[i]%2==0){
oddcheck = false;
}
// RELEVANT TO QUESTION.
// A prime number can only be divided by 1 and inself.
// Divide FibNums[i] by every number inbetween.
// If a number divides evenly, it is not a prime (exception: 2).
// Else, the number is a prime.
boolean primecheck;
for (int divisor = 2; divisor < FibNums[i]/2; divisor++){
if (FibNums[i] % divisor == 0){
primecheck = false;
} else {
primecheck = true;
}
// REVELANT TO QUESTION.
// Add FibNums[i] to the FibPrimes[n] array if it is a prime.
if (primecheck == false){
FibPrimes[n] = FibNums[i];
n = n + 1;
}
// RELEVANT TO QUESTION.
// If any element in the FibPrimes array is equal to the FibNums
// array, then the number is a prime.
for (n=0; n<FibPrimes.length; n++){
if (FibNums[i] == FibPrimes[n]){
System.out.print("This is a prime." + " ");
}
}
// Prints odd fibonacci numbers with a star beside it.
// Prints even fibonacci numbers with no star beside it.
if (oddcheck == true){
System.out.println(FibNums[i] + "*");
} else {
System.out.println(FibNums[i]);
}
FibSum = FibSum + FibNums[i];
} // End number generation loop.
System.out.print ( "The average is" + " " + FibSum/20);
}
}
Output:
0
1*
The average is 0The average is 0The average is 0The average is 0This is a prime. 8
This is a prime. 8
The average is 013*
13*
13*
13*
The average is 321*
This is incorrect.
Previous Attempt:
This solution "worked", but in order to not take the "lazy route" I must do the calculations using code. Only relevant snippets are shown:
// Creation if Fibonacci Primes Array.
// Ideally, this should be caulculated.
int [] FibPrimes = new int[7];
FibPrimes[0] = 2;
FibPrimes[1] = 3;
FibPrimes[2] = 5;
FibPrimes[3] = 13;
FibPrimes[4] = 89;
FibPrimes[5] = 233;
FibPrimes[6] = 1597;
// If any element in the FibPrimes array is equal to the FibNums
// array, then the number is a prime.
for (int n=0; n<FibPrimes.length; n++){
if (FibNums[i] == FibPrimes[n]){
System.out.print("This is a prime." + " ");
}
}
Output:
0
1*
1*
This is a prime. 2
This is a prime. 3*
This is a prime. 5*
8
This is a prime. 13*
21*
34
55*
This is a prime. 89*
144
This is a prime. 233*
377*
610
987*
This is a prime. 1597*
2584
4181*
The average is 547
This is the desired output! However, I cannot use this because I must calculate the prime fibonacci numbers using code. This is the "lazy route".
Thank you.
Just 10 mins on google and you will be able to create something simple and fast.
Using the mathematical formulas below :
which you can find more one this paper you can make your prime fibonacci sequence. In addition you will need a way to check which numbers in the sequence are primes so a quick way is through AKS algorithm
Here is a full example of all the above :
public class FibonacciSequence {
public static void main(String[] args) {
for (int i = 1; i <= 20; i++) {
int num = (int) ((getY_1(i) - getY_2(i)) / Math.sqrt(5));
if (isPrime(num)) {
System.out.print("This is a prime : ");
}
System.out.println(num);
}
}
public static double getY_1(int N) {
return Math.pow((1 + Math.sqrt(5.0)) / 2.0, N);
}
public static double getY_2(int N) {
return Math.pow((1 - Math.sqrt(5.0)) / 2.0, N);
}
public static boolean isPrime(int num) {
if (num == 2 || num == 3)
return true;
if (num % 2 == 0 || num % 3 == 0) {
return false;
}
int i = 5;
int s = 2;
while (i * i <= num) {
if (num % i == 0) {
return false;
}
i += s;
s = 6 - s;
}
return true;
}
}
Of course you can exclude the value (1) if you don't feel like identifying it as a prime :P.
Output :
This is a prime : 1
This is a prime : 1
This is a prime : 2
This is a prime : 3
This is a prime : 5
8
This is a prime : 13
21
34
55
This is a prime : 89
144
This is a prime : 233
377
610
987
This is a prime : 1597
2584
4181
6765
P.S : I had free time :P

I have a program that calculates the first 200 prime numbers, but I do not understand a formula in it

I need to write a code which should calculate the first 200 prime numbers, but I can't hand it in as long as I can't explain everything. I used a piece of code from the internet as reference (http://crab.rutgers.edu/~dhong/cs325/chapter3/PrimeNumber.java).
Whole code:
public class Opdracht3 {
public static void main(String[] args) {
int limiet = 200;
int counter = 1;
int testpriem = 3;
boolean isPriem;
while (counter <= limiet) {
isPriem = true;
for (int i = 2; i <= testpriem / 2; i++) {
if (testpriem % i == 0) {
isPriem = false;
break;
}
}
if (isPriem) {
System.out.println(counter + ": " + testpriem);
counter++;
}
testpriem++;
}
}
}
Below part of code verifies if the number is a composite. If testpriem is composite, then comes out of the loop and starts over. Otherwise, it continues and prints the prime number testpriem.
The problem is here:
for (int i = 2; i <= testpriem / 2; i++) {
if (testpriem % i == 0) {
isPriem = false;
break;
}
}
I tested what happens to i, and one way or another it recognizes the divisor needed to calculate the composite. (With 4 divisor is 2, with 9 divisor is 3, with 221 divisor is 13) But I am flabbergasted as of why.
Any ideas?.
the % or ("remainder") operator in Java divides one operand by another and returns the remainder as its result. And of course if integer x is evenly divisible by another integer y (meaning x/y = some integer z with a remainder of zero), then x can not be prime.
First remember every number able to divide by its half or less. Consider number 7 it is possible divided by 1,2,3 because after 3, if try to divide number by 4 means 4x2 = 8 that is greater than 7. so it is optimum way to find divisor in this way. One more thing every number divided by 1 and number itself. so if number number is divided by 1 or itself then it is called prime so i starts from 2.
now consider testpriem =7 so you will get loop like
for (int i = 2; i <= 7 / 2(i.e 3); i++)
{
if(7 % i == 0)
{
isPriem = false;
break;
}
so first time it checks 7%2=1 so condition false. again check for 7%3 = 1 again condition false. and now this condition full fills here i <= 7 / 2(i.e 3) so loop stopped and it result 7 number is prime
Well, if testpriem % i == 0, it means that i divides testpriem, which means that testpriem is not a prime a number and i, is its first divider. % is the modulo operation, which is the rest of the division.
https://en.wikipedia.org/wiki/Modulo_operation
The break stops the for loop and moves to the next position in the while loop. So it does not restart the for loop for the current tested number.
The break is used for efficiency reasons. You could remove it and the algorithm would still work correctly but slower.

How do I do Euler 5 without bruteforcing?

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.

Project Euler #3 - Solution runs forever

First time I've ever encountered this problem. It feels like it will never end.
My approach:
import java.util.TreeSet;
public class Euler3 {
public static void main(String[] args) {
long result = 0;
long startTime = System.nanoTime();
long numberGiven = 600851475143L;
TreeSet<Long> nums = new TreeSet<>();
for (long i = 2L; i < numberGiven; i++) {
if (numberGiven % i == 0 && isPrime(i)) {
nums.add(i);
}
}
result = nums.last();
System.out.print("Result: " + result +
".\nTime used for calculation in nanoseconds: " +
(System.nanoTime() - startTime) + ".");
}
public static boolean isPrime(long n) {
if (n <= 3) {
return n == 1 ? false : true;
} else if (n % 2 == 0 || n % 3 == 0) {
return false;
} else {
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
return true;
}
}
}
Of course this works on smaller numbers, but as is probably intended doesn't seem effective on over 600 billion.
I'm wondering, without giving the answer away:
Is there some obvious alteration I could employ to reduce the
running time/checks necessary?
Although it clearly doesn't work effectively here, is this approach
otherwise acceptable or would someone who posted this challenge,
even with a smaller number, be looking for something different?
I tried with integers the first time and got an overflow related error, is anything similar happening under the hood that would actually prevent this from terminating?
For every number you're checking that's a factor, you're doing an internal loop to figure out if it's a prime. That means your algorithm is effectively performing n * m operations.
You can instead use the following mathematical "trick", which I think is the same used by the UNIX factor program.
Since every number over one is either prime or a unique product of a set of primes (with potential duplicates in the set), we can just start dividing the number by the first prime two (actually reducing the number in the process) until that's no longer possible (i.e., it becomes odd). At that point, the reduced number will not have two or any multiples of two as a factor.
Then we do the same by continuously dividing by three until that's no longer possible.
Now you'd think that may be onerous but, because you've stripped out all the 'two' factors, the number cannot possibly be a multiple of four (or any other even number for that matter). So we detect that and move up to the next divisor of five and start dividing by that.
So the division operation are only done for prime divisors, speeding things up considerably. In addition, once the divisor gets above the square root of the (reduced) number, no more factors are possible, so we exit. In that case, the reduced number gives us the final (hence highest) prime factor.
For example, consider the number 924:
Number Divisor Result
------ ------- ------
924 2* 462
462 2* 231
231 2 not divisible, go to 3
231 3* 77
77 3 not divisible, go to 4
77 4 not divisible, go to 5
77 5 not divisible, go to 6
77 6 not divisible, go to 7
77 7* 11
11* 7 stop since 7 * 7 > 11
So the prime factors of 924 are {2, 2, 3, 7, 11}.
Now I urge you to try that algorithm on your own before looking below since the entire point of Euler is to test your own abilities. I simply provide the solution for completeness:
public class Test
{
public static void main(String[] args) {
long startTime = System.nanoTime();
long number = 600851475143L;
// Start with a divisor of two,
// continue until over sqrt(number).
long divisor = 2L;
while (divisor * divisor <= number) {
if ((number % divisor) == 0) {
// If factor, output then reduce number.
System.out.println(divisor);
number = number / divisor;
} else {
// Otherwise, move to next divisor.
divisor++;
}
}
// Final number is final divisor.
System.out.println(number);
System.out.print("Time used for calculation in nanoseconds: " +
(System.nanoTime() - startTime) + ".");
}
}
That gives you the four prime factors in about five thousandths of a second (on my box, anyway):
71
839
1471
6857
Time used for calculation in nanoseconds: 458826.
The program can be simple like this, which runs under a second:
long val = 600851475143L;
long ans = 0;
for(long i = 2; i*i <= val; i++){
if(val % i == 0){
ans = i;
while(val % i == 0)//This step will make sure that i is prime
val /= i;
}
}
if(val != 1){//If val is not 1, so val is a prime
ans = val > ans ? val : ans;
}
System.out.println(ans);
Answer is 6857, and it is correct answer :)
Notice that we only check for all i values which i*i smaller than val.

Prime Factorization Program in Java

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

Categories

Resources