Class that checks for primes not working properly - java

I made a class called Primes for everything related to prime numbers. It contains a method called isPrime, which uses another method called sieveOfAtkin that creates a boolean array called sieve that has index values from 0 to 1000000. The user passes an integer n to the isPrime method. If sieve[n]=true, then the integer n is a prime number. Otherwise isPrime returns false. My problem is that when I tested this method using numbers that I know are prime, it always returns false. Take this line of code for example that tests whether 13 is a prime number:
public class Test {
public static void main(String[] args) {
Primes pr=new Primes(); // Creates Primes object
System.out.println(pr.isPrime(13));
}
}
The output is false, even though we know that 13 is a prime number. Here is my code for the entire Primes class https://github.com/javtastic/project_euler/blob/master/Primes.java
It uses a sieve of atkin, which is supposed to be the most efficient method of testing for primes. More info on that can be found here: http://en.wikipedia.org/wiki/Sieve_of_Atkin
I'm not entirely sure what I am doing wrong. I have been trying for hours to figure out what is causing this error and I still get the same results (everything is false). Perhaps I should find a different way of checking primes?

Use this:
public static boolean isPrime(int number) {
int sqrt = (int) Math.sqrt(number) + 1;
for (int i = 2; i < sqrt; i++) {
if (number % i == 0) {
return false;
}
}
return true;
}

The code works like a charm for me, no changes done.
code
import java.util.Arrays;
public class Test {
// This class uses a Atkin sieve to determine all prime numbers less than int limit
// See http://en.wikipedia.org/wiki/Sieve_of_Atkin
private static final int limit = 1000000;
private final static boolean[] sieve = new boolean[limit + 1];
private static int limitSqrt = (int) Math.sqrt(limit);
public static void sieveOfAtkin() {
// there may be more efficient data structure
// arrangements than this (there are!) but
// this is the algorithm in Wikipedia
// initialize results array
Arrays.fill(sieve, false);
// the sieve works only for integers > 3, so
// set these trivially to their proper values
sieve[0] = false;
sieve[1] = false;
sieve[2] = true;
sieve[3] = true;
// loop through all possible integer values for x and y
// up to the square root of the max prime for the sieve
// we don't need any larger values for x or y since the
// max value for x or y will be the square root of n
// in the quadratics
// the theorem showed that the quadratics will produce all
// primes that also satisfy their wheel factorizations, so
// we can produce the value of n from the quadratic first
// and then filter n through the wheel quadratic
// there may be more efficient ways to do this, but this
// is the design in the Wikipedia article
// loop through all integers for x and y for calculating
// the quadratics
for (int x = 1 ; x <= limitSqrt ; x++) {
for (int y = 1 ; y <= limitSqrt ; y++) {
// first quadratic using m = 12 and r in R1 = {r : 1, 5}
int n = (4 * x * x) + (y * y);
if (n <= limit && (n % 12 == 1 || n % 12 == 5)) {
sieve[n] = !sieve[n];
}
// second quadratic using m = 12 and r in R2 = {r : 7}
n = (3 * x * x) + (y * y);
if (n <= limit && (n % 12 == 7)) {
sieve[n] = !sieve[n];
}
// third quadratic using m = 12 and r in R3 = {r : 11}
n = (3 * x * x) - (y * y);
if (x > y && n <= limit && (n % 12 == 11)) {
sieve[n] = !sieve[n];
}
// note that R1 union R2 union R3 is the set R
// R = {r : 1, 5, 7, 11}
// which is all values 0 < r < 12 where r is
// a relative prime of 12
// Thus all primes become candidates
}
}
// remove all perfect squares since the quadratic
// wheel factorization filter removes only some of them
for (int n = 5 ; n <= limitSqrt ; n++) {
if (sieve[n]) {
int x = n * n;
for (int i = x ; i <= limit ; i += x) {
sieve[i] = false;
}
}
}
}
// isPrime method checks to see if a number is prime using sieveOfAtkin above
// Works since sieve[0] represents the integer 0, sieve[1]=1, etc
public static boolean isPrime(int n) {
sieveOfAtkin();
return sieve[n];
}
public static void main(String[] args) {
System.out.println(isPrime(13));
}
}
Input - 13, Output - True
Input -23, Output - True
Input - 33. output - False

Related

Time Complexity Improvement for Project Euler Solution

This is my solution to the first question in Project Euler.
Could someone please help reduce the time complexity of this working code?
Problem:
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
public class Sum {
private static final int n = 1000;
public static void main(String[] args) {
for (int i = 1, sum = 0; i <= n; i++) {
if ((i % 3 == 0) || (i % 5 == 0)) {
System.out.println(sum += i);
}
}
}
}
I am using the formula provided by phatfingers.
You can have numbers that are divisible by 15 (3 * 5), so you kinda have to subtract that amount.
Because the formula without k works for all natural numbers up to n, you multiply the thing by k. But this expands your scale by a factor of k, so I divided n by k (automatically being rounded down).
public class Sum {
private static final int n = 15;
public static void main(String[] args) {
int result = compute(3, n) + compute(5, n) - compute(15, n);
System.out.println(result);
}
private static int compute(int k, int n) {
n = n / k;
return k * n * (n + 1) / 2;
}
}
Note:
You can declare your variables inside of the for-loop
You check i < n (n exclusive) instead of i <= n (n inclusive, which I think you want here). If you don't want this, change n = n / k to n = (n - 1) / k.

Represent an Integer as a sum of Consecutive positive integers

I am writing code for counting the number of ways an integer can be represented as a sum of the consecutive integers. For Example
15=(7+8),(1+2+3+4+5),(4+5+6). So the number of ways equals 3 for 15.
Now the input size can be <=10^12. My program is working fine till 10^7(i think so, but not sure as i didnt check it on any online judge. Feel free to check the code for that)
but as soon as the i give it 10^8 or higher integer as input. it throws many runtime exceptions(it doesnt show what runtime error). Thanks in advance.
import java.io.*;
//sum needs to contain atleast 2 elements
public class IntegerRepresentedAsSumOfConsecutivePositiveIntegers
{
public static long count = 0;
public static void main(String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
long num = Long.parseLong(br.readLine()); //Enter a number( <=10^12)
driver(num);
System.out.println("count = " + count);
}
public static void driver(long num)
{
long limit = num / 2;
for(long i = 1 ; i <= limit ; i++)
{
func(i,num);
}
}
public static void func(long i,long num)
{
if(i < num)
{
func(i + 1,num - i);
}
else if(i > num)
{
return;
}
else
{
count++;
}
}
}
Use some math: if arithmetic progression with difference 1 starts with a0 and contains n items, then its sum is
S = (2 * a0 + (n-1))/2 * n = a0 * n + n * (n-1) / 2
note that the second summand rises as quadratic function. So instead of checking all a0 in range S/2, we can check all n is smaller range
nmax = Ceil((-1 + Sqrt(1 + 8 * S)) / 2)
(I used some higher approximation).
Just test whether next expression gives integer positive result
a0 = (S - n * (n - 1) / 2) / n
Recursive function isn't suitable when you have big input size like your case.
The maximum depth of the java call stack is about 8900 calls and sometimes only after 7700 calls stack overflow occurs so it really depends on your program input size.
Try this algorithm I think it worked for your problem:
it will work fine until 10^9 after that it will take much more time to finish running the program.
long sum = 0;
int count = 0;
long size;
Scanner in = new Scanner(System.in);
System.out.print("Enter a number <=10^12: ");
long n = in.nextLong();
if(n % 2 != 0){
size = n / 2 + 1;
}
else{
size = n / 2;
}
for(int i = 1; i <= size; i++){
for(int j = i; j <= size; j++){
sum = sum + j;
if(sum == n){
sum = 0;
count++;
break;
}
else if(sum > n){
sum = 0;
break;
}
}
}
System.out.println(count);
Output:
Enter a number <=10^12: 15
3
Enter a number <=10^12: 1000000000
9
BUILD SUCCESSFUL (total time: 10 seconds)
There's a really excellent proof that the answer can be determined by solving for the unique odd factors (Reference). Essentially, for every odd factor of a target value, there exists either an odd series of numbers of that factor multiplied by its average to produce the target value, or an odd average equal to that factor that can be multiplied by double an even-sized series to reach the target value.
public static int countUniqueOddFactors(long n) {
if (n==1) return 1;
Map<Long, Integer> countFactors=new HashMap<>();
while ((n&1)==0) n>>>=1; // Eliminate even factors
long divisor=3;
long max=(long) Math.sqrt(n);
while (divisor <= max) {
if (n % divisor==0) {
if (countFactors.containsKey(divisor)) {
countFactors.put(divisor, countFactors.get(divisor)+1);
} else {
countFactors.put(divisor, 1);
}
n /= divisor;
} else {
divisor+=2;
}
}
int factors=1;
for (Integer factorCt : countFactors.values()) {
factors*=(factorCt+1);
}
return factors;
}
As #MBo noted, if a number S can be partitioned into n consecutive parts, then S - T(n) must be divisible by n, where T(n) is the n'th triangular number, and so you can count the number of partitions in O(sqrt(S)) time.
// number of integer partitions into (at least 2) consecutive parts
static int numberOfTrapezoidalPartitions(final long sum) {
assert sum > 0: sum;
int n = 2;
int numberOfPartitions = 0;
long triangularNumber = n * (n + 1) / 2;
while (sum - triangularNumber >= 0) {
long difference = sum - triangularNumber;
if (difference == 0 || difference % n == 0)
numberOfPartitions++;
n++;
triangularNumber += n;
}
return numberOfPartitions;
}
A bit more math yields an even simpler way. Wikipedia says:
The politeness of a positive number is defined as the number of ways it can be expressed as the sum of consecutive integers. For every x, the politeness of x equals the number of odd divisors of x that are greater than one.
Also see: OEIS A069283
So a simple solution with lots of room for optimization is:
// number of odd divisors greater than one
static int politeness(long x) {
assert x > 0: x;
int p = 0;
for (int d = 3; d <= x; d += 2)
if (x % d == 0)
p++;
return p;
}

Largest prime factor of a number in Java

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

How do I print the factorials of 0-30 on a table

public static void main(String[] args) {
int n = factorial(30);
int x = 0;
while (x <= 30) {
System.out.println(x + " " + n);
x = x + 1;
}
public static int factorial (int n) {
if (n == 0) {
return 1;
} else {
return n * factorial (n-1);
}
}
}
I'm trying to print out something like this:
0 1
1 1
2 2
3 6
4 24
...etc, up to 30 (30!)
What I'm getting instead is this:
0 (30!)
1 (30!)
...etc, up to 30
In words, I'm able to create the left column from 0 to 30 but I want to make it print the factorial of the numbers in the right hand column. With my code, it only prints the factorial of 30 in the right-hand column. I want it to print the factorials in order next to their corresponding number. How can I fix my code to do this?
This is pretty simple. Instead of defining a variable, you call the method with the updated x every time:
System.out.println(x + " " + factorial(x));
Note that your loop could be rewritten as a for loop, which is exactly what they're designed for:
for (int x = 0; x < 30; x++) {
System.out.println(x + " " + factorial(x));
}
Note a couple of things:
The x++. It's basically a short form of x = x + 1, though there are some caveats. See this question for more information about that.
x is defined in the loop (for (int x = ...) not before it
n is never defined or used. Rather than setting a variable that's only used once, I directly used the result of factorial(x).
Note: I'm actually pretty certain that an int will overflow when confronted with 30!. 265252859812191058636308480000000 is a pretty big number. It also overflows long, as it turns out. If you want to handle it properly, use BigInteger:
public BigInteger factorial(int n) {
if (n == 0) {
return BigInteger.ONE;
} else {
return new BigInteger(n) * factorial(n - 1);
}
}
Because of BigInteger#toString()'s magic, you don't have to change anything in main to make this work, though I still recommend following the advice above.
As #QPaysTaxes explains, the issue in your code was due to computing the final value and then printing it repeatedly rather than printing each step.
However, even that working approach suffers from a lack of efficiency - the result for 1 computes the results for 0 and 1, the result for 2 computes the results for 0, 1, and 2, the result for 3 computes the results for 0, 1, 2, and 3, and so on. Instead, print each step within the function itself:
import java.math.BigInteger;
public class Main
{
public static BigInteger factorial (int n) {
if (n == 0) {
System.out.println("0 1");
return BigInteger.ONE;
} else {
BigInteger x = BigInteger.valueOf(n).multiply(factorial(n - 1));
System.out.println(n + " " + x);
return x;
}
}
public static void main(String[] args)
{
factorial(30);
}
}
Of course, it would be faster and simpler to just multiply in the loop:
import java.math.BigInteger;
public class Main
{
public static void main(String[] args)
{
System.out.println("0 1");
BigInteger y = BigInteger.ONE;
for (int x = 1; x < 30; ++x) {
y = y.multiply(BigInteger.valueOf(x));
System.out.println(x + " " + y);
}
}
}
Just for fun, here's the efficient recursive solution in Python:
def f(n):
if not n:
print(0, 1)
return 1
else:
a = n*f(n-1)
print(n, a)
return a
_ = f(30)
And, better still, the iterative solution in Python:
r = 1
for i in range(31):
r *= i or 1
print(i, r)

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.

Categories

Resources