isEvenSubset did not return 1 - java

Here is the Question: An integer is defined to be an even subset of another integer n if every even factor of m is also a factor of n. For example 18 is an even subset of 12 because the even factors of 18 are 2 and 6 and these are both factors of 12. But 18 is not an even subset of 32 because 6 is not a factor of 32.
This is a University's sample question; the question, explicitly, states: No additional data structures including arrays allowed - therefore, please consider that too while providing answer. Thank you.
Here is my answer code:
public class IsEvenSubset {
public static void main(String[] args) {
System.out.println(isEvenSubset(18,12));
}
private static int isEvenSubset(int m, int n){
for(int i=2;i<=m;i++){
int count=0;//reset count in each round
if(m%2==0 && m%i==0){
for(int j=2;j<=n;j++){
if(n%2==0 && n%j==0){
if(i==j)count++;
}
}
if(count==0)return 0;
}
}
return 1;
}
}
This code didn't work as desired. Please help me figure out where did I do wrong?

You are checking whether m and n are even instead of whether their factors are even. Besides, the inner loop is not needed, just find all the even factors of the first number and check whether all of them are also factors of the second number.
private static boolean isEvenSubset (int m, int n)
{
for(int i = 2; i < m; i++){ // note that I don't consider m itself to be a factor of m
if (i % 2 == 0 && m % i == 0 && n %i != 0){ // i is an even factor of m but
// not a factor of n, so return false
return false;
}
}
return true; // all the even factors of m were also factors of n
}
isEvenSubset(18,12) returns true and isEvenSubset(18,32) returns false.

Related

Java throwing division by zero error?

In an attempt to relearn how to write code in Java I've been going through some problems from Project Euler. The following code I've written is to solve problem 3: finding the largest prime factor of the number 600851475143.
public class ProjectEuler {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
ProjectEuler t = new ProjectEuler();
System.out.println(t.findLargestPrime(600851475143L));
}
public Boolean isPrime(int x) {
Boolean answer = true;
for (int i = 2; i < x/2; i++) {
if (x%i == 0) {
answer = false;
}
}
return answer;
}
public int findLargestPrime(Long max) {
int largest = 1;
for (int i = 2 ; i < max/2; i++) {
if (max%i == 0 && isPrime(i) && i > largest) {
largest = i;
}
}
return largest;
}
}
However, when I run it the code throws an arithmetic error because I'm trying to divide by zero? The actual error message is shown here:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at projecteuler.ProjectEuler.findLargestPrime(ProjectEuler.java:37)
at projecteuler.ProjectEuler.main(ProjectEuler.java:19)
I don't know if I've made a stupid mistake somewhere or if it's a quirk of Java that I don't understand? Could anyone shed some light on this?
Thank you.
for (int i = 2 ; i < max/2; i++) will eventually overflow (because 600851475143 / 2 is bigger than Integer.MAX_VALUE) and eventually i will equal to 0 when it will happen max%i will throw that exception.
Change i to long if you want to prevent it from happeninng (you should also change all the other int's to long).
This is not an answer to the actual question, but: You do not have to check all the numbers up to max, and you do not even have to do any checks whether a divisor is prime. You just have to (repeatedly) divide the max by any divisor i you found.
long l = 600851475143L;
for (int i = 2; i <= Math.sqrt(l); i++) {
if (l % i == 0) {
System.out.println(i);
l /= i;
i--;
}
}
System.out.println("--> " + l);
This way, you know that this divisor must be prime -- if it were composite, max would already have been divided by its components. This also means that you do not have to loop all the way up to max (which, for the given value, would take a really long time), but only up to the largest prime divisor, which might be much much smaller. And once you reach sqrt(l) -- for the current value of l, not the original! -- you can stop, since there can not be any divisors higher than that, and the remaining value of l will be the final (and thus, largest) prime factor.
Thus, this reduces the complexity from about O(n²) to about O(n½).

How to optimize algorithm to be able to determine 10 digit long prime numbers in java

I am currently new to java and programming in general, I'm working on an algorithm that determines the prime numbers in specific given ranges. Currently it works with six ranges which are numbers under 1 billion, when I tried to determine a 10 digit long number it failed. I am aware it needs to be changed to long since the digit is out of range but I am not sure how.
this is the part of the code where it determines if the umber is prime:
public ArrayList<Integer> getPrimes(int StartPos, int n) {
ArrayList<Integer> primeList = new ArrayList<>();
boolean[] primes = new boolean[n + 1];
for (int i = StartPos; i < primes.length; i++) {
primes[i] = true;
}
int num = 2;
while (true) {
for (int i = 2;; i++) {
int m = num * i;
if (m > n) {
break;
} else {
primes[m] = false;
}
}
boolean nextNum = false;
for (int i = num + 1; i < n + 1; i++) {
if (primes[i]) {
num = i;
nextNum = true;
break;
}
}
if (!nextNum) {
break;
}
}
for (int i = 0; i < primes.length; i++) {
if (primes[i]) {
primeList.add(i);
}
}
return primeList;
}
I was checking online and found that perhaps I could do it with vectors but I have no experience with them and Also they are relatively slower than an Array.
You might try BigInteger#isProbablePrime: https://www.tutorialspoint.com/java/math/biginteger_isprobableprime.htm
import java.math.BigInteger;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
// Java 8
public class FindPrimes {
public static void main(String[] args) {
System.out.println("1 - 100 primes: " + findPrimes(1L, 99L));
System.out.println("some 10-digit primes: " + findPrimes(99_999_999_999L, 20000L));
}
private static List<Long> findPrimes(long start, long quant) {
return LongStream.rangeClosed(start, start + quant).filter(v ->
BigInteger.valueOf(v).isProbablePrime(1)).boxed().collect(Collectors.toList());
}
}
You say you are learning, so I will give you an outline in pseudocode, not the answer.
In general the method to find a prime in a range is:
repeat
pick a number in the range
until (the number is prime)
You want a ten digit number. One way to generate a candidate while avoiding obvious non-primes is:
start with digit in [1..9] // No leading zero.
repeat 8 times
append a digit in [0..9]
endrepeat
append a digit in [1, 3, 7, 9] // Final digits for large primes.
That will give you a ten digit possible prime.
Now you need to test to check it is prime.
There are tests like Miller-Rabin that you could try, but probably not if you are a real beginner. I would suggest setting up a Sieve of Eratosthenes covering numbers to to 10,000 which is the square root of your upper limit of 10,000,000,000. That will give you fast access to all the primes below the square root of your number. Set up the sieve once only at the start of your program. Make it a separate Class, and include a int nextPrime(int n) method which returns the next prime after the supplied parameter. Once that is in place, then you can write a trial division method to test your ten digit number:
boolean method isPrime(tenDigitNumber)
testPrime <- 2
limit <- square root of tenDigitNumber // Only calculate this once.
while (testPrime < limit)
if (tenDigitNumber MOD testPrime == 0)
return false // Number is not prime.
else
testPrime <- sieve.nextPrime(testPrime)
endif
endwhile
return true // If we get here then the number is prime.
end isPrime
Because you have set up the sieve in advance, this should run reasonably quickly. If it is too slow, then it is time to look at coding Miller-Rabin or one of the other heavy-duty prime test methods.
As well as the Sieve of Eratosthenes class, another useful utility method is an iSqrt() method that returns an integer square root. My own version uses the Newton-Raphson method, though no doubt there are other possibilities.

Stack overflow error in Java recursion

I'm trying to implement a code that returns the sum of all prime numbers under 2 million. I have an isPrime(int x) method that returns true if the the number is prime. Here it is:
public static boolean isPrime(int x) {
for (int i = 2; i < x; i++) {
if (x % i == 0) {
return false;
}
}
return true;
}
And the other method, which I'm trying to implement recursively, only works until a certain number, over that number and I get a stack overflow error. The highest I got the code to work was for 10,000.
Here it is:
public static int sumOfPrimes(int a) {
if (a < 2000000) { //this is the limit
if (isPrime(a)) {
return a + sumOfPrimes(a + 1);
} else {
return sumOfPrimes(a + 1);
}
}
return -1;
}
So why do I get a stack overflow error when the number gets bigger and how can I deal with this?
Also, how do you normally deal with writing code for such big numbers? IE: normal number operations like this but for larger numbers? I wrote this recursively because I thought it would be more efficient but it still wont work.
Your isPrime function is inefficient, it doesn't have to go to x, it's enough to go to the square root of x.
But that is not the reason why your solution doesn't work. You cannot have a recursion depth of 1 million.
I would solve this problem iteratively, using the sieve of eratosthenes and for loop over the resulting boolean array.
In general if you would still like to use recursion, you can use tail recursion.
In recursion each function call will push some data to the stack, which is limited, thus generating a stackoverflow error. In tail recursion you won't be pushing anything to the stack, thus not throwing the exception.
Basically all you need is sending the data of the previous computation as parameter instead of having it on the stack.
So:
function(int x) {
// end condition
return function(x - 1) + x;
}
with tail recursion would be
function (int max, int curr, int prev, int sum) {
if (curr > max)
return sum;
return function (max, curr + 1, curr, sum + curr)
}
Keep in mind this is just pseudo code not real java code, but is close enough to the java code.
For more info check
What is tail recursion?
Use Sieve of Eratosthenes:-
Following is the algorithm to find all the prime numbers less than or equal to a given integer n by Eratosthenes’ method:
1) Create a list of consecutive integers from 2 to n: (2, 3, 4, …, n).
2) Initially, let p equal 2, the first prime number.
3) Starting from p, count up in increments of p and mark each of these numbers greater than p itself in the list. These numbers will be 2p, 3p, 4p, etc.; note that some of them may have already been marked.
4) Find the first number greater than p in the list that is not marked. If there was no such number, stop. Otherwise, let p now equal this number (which is the next prime), and repeat from step 3.
public static void main(String[] args) {
int n = 30;
System.out.printf("Following are the prime numbers below %d\n", n);
SieveOfEratosthenes(n);
}
static void markMultiples(boolean arr[], int a, int n)
{
int i = 2, num;
while ( (num = i*a) <= n )
{
arr[ num-1 ] = true; // minus 1 because index starts from 0.
++i;
}
}
// A function to print all prime numbers smaller than n
static void SieveOfEratosthenes(int n)
{
// There are no prime numbers smaller than 2
if (n >= 2)
{
// Create an array of size n and initialize all elements as 0
boolean[] arr=new boolean[n];
for(int index=0;index<arr.length-1;index++){
arr[index]=false;
}
for (int i=1; i<n; ++i)
{
if ( arr[i] == false )
{
//(i+1) is prime, print it and mark its multiples
System.out.printf("%d ", i+1);
markMultiples(arr, i+1, n);
}
}
}
}
Output:-
Following are the prime numbers below 30
2 3 5 7 11 13 17 19 23 29

Optimizing recursive method

I have some code that needs to run with some rather large numbers, and it involves incrementing into a recursive method and is therefor very slow to the point where I can't even get to my desired answer. Could someone help me optimize it? I am a beginner though, so I can't do anything very complex/difficult.
public class Euler012{
public static void main(String[]args){
int divisors=0;
for(long x=1;divisors<=501;x++){
divisors=1;
long i=triangle(x);
for(int n=1;n<=i/2;n++){
if(i%n==0){
divisors++;
}
}
//System.out.println(divisors+"\n"+ i);
System.out.println(i+": " + divisors);
}
}
public static long triangle(long x){
long n=0;
while(x>=0){
n+=x;
x--;
triangle(x);
}
return n;
}
}
First: i don't think its an optimization problem, because its a small task, but as mentioned in the comments you do many unnecessary things.
Ok, now lets see where you can optimize things:
recursion
recursion has usually a bad performance, especially if you don't save values this would be possible in your example.
e.g.: recursive triangle-number function with saving values
private static ArrayList<Integer> trianglenumbers = new ArrayList<>();
public static int triangleNumber(int n){
if(trianglenumbers.size() <= n){
if(n == 1)
trianglenumbers.add(1);
else
trianglenumbers.add(triangleNumber(n-1) + n);
}
return trianglenumbers.get(n-1);
}
but as mentioned by #RichardKennethNiescior you can simply use the formula:
(n² + n)/2
but here we can do optimization too!
you shouldnt do /2 but rather *0.5 or even >>1(shift right)
but most compilers will do that for you, so no need to make your code unreadable
your main method
public static void main(String[]args){
int divisors = 0; //skip the = 0
for(long x=1;divisors<=501;++x){ // ++x instead of x++
divisors=0;
long i=(x*x + x) >> 1; // see above, use the one you like more
/*how many divisors*/
if(i == 1) divisors = 1;
else{ /*1 is the only number with just one natural divisor*/
divisors = 2; // the 1 and itself
for(int n = 2; n*n <= i; ++n){
if(n*n == i) ++divisors;
else if(i%n == 0) divisors += 2;
}
}
System.out.println(i+": " + divisors);
}
}
the ++x instead of x++ thing is explained here
the how many divisors part:
every number except 1 has at least 2 divisors (primes, the number itself and one)
to check how many divisors a number has, we just need to go to the root of the number
(eg. 36 -> its squareroot is 6)
36 has 9 divisors (4 pares) {1 and 36, 2 and 18, 3 and 12, 4 and 8, 6 (and 6)}
1 and 36 are skiped (for(**int n = 2**)) but counted in divisors = 2
and the pares 2, 3 and 4 increase the number of divisors by 2
and if its a square number (n*n == i) then we add up 1
You dont have to generate a new triangle number from scratch each time, if you save the value to a variable, and then add x to it on the next iteration, you dont really need to have the triangle method at all.

Project Euler Number 3

First of all, this isn't homework... working on this outside of class to get some practice with java.
public class Problem3 {
public static void main(String[] args) {
int n = 13195;
// For every value 2 -> n
for (int i=2; i < n; i++) {
// If i is a multiple of n
if (n % i == 0) {
// For every value i -> n
for (int j=2; j < i; j++) {
if (n % j != 0) {
System.out.println(i);
break;
}
}
}
}
}
}
I keep modifying the code to try to make it do what I want.
As the problem says, you should be getting 5, 7, 13 and 29.
I get these values, plus 35, 65, 91, 145, 203, 377, 455, 1015, 1885, and 2639. I think I'm on the right track as I have all the right numbers... just have a few extras.
And in checking a few of the numbers in both being divisible by n and being prime numbers, the issue here is that the extra numbers aren't prime. Not sure what's going on though.
If anyone has any insight, please share.
This part
for (int j=2; j < i; j++) {
if (n % j != 0) {
System.out.println(i);
break;
}
doesn't check whether i is prime. Unless i is small, that will always print i at some point, because there are numbers smaller than i that don't divide n. So basically, that will print out all divisors of n (It wouldn't print the divisor 4 for n == 12, for example, but that's an exception).
Note also that the algorithm - using long instead of int to avoid overflow - even if fixed to check whether the divisor i is prime for deciding whether to print it, will take a long time to run for the actual target. You should investigate to find a better algorithm (hint: you might want to find the complete prime factorisation).
I solved this problem in Java and looking at my solution the obvious advice is start using BigInteger, look at the documentation for java.math.BigInteger
Also a lot of these problems are "Math" problems as much as they are "Computer Science" problems so research the math more, make sure you understand the math reasonably well, before coming up with your algorithm. Brute force can work some times, but often there are tricks to these problems.
Brut force can also work for checking whether factor is prime or not for this problem...
eg.
for(i=1;i<=n;i++)// n is a factor.
{
for(j=i;j>=1;j--)
{
if(i%j==0)
{
counter++;// set counter=0 befor.
}
if(counter==2) // for a prime factor the counter will always be exactly two.
{
System.out.println(i);
}
counter=0;
}
}
Don't know about Java but here is my C code if it is of any help.
# include <stdio.h>
# include <math.h>
// A function to print all prime factors of a given number n
void primeFactors(long long int n)
{
// Print the number of 2s that divide n
while (n%2 == 0)
{
printf("%d ", 2);
n = n/2;
}
int i;
// n must be odd at this point. So we can skip one element (Note i = i +2)
for ( i = 3; i <= sqrt(n); i = i+2)
{
// While i divides n, print i and divide n
while (n%i == 0)
{
printf("%d ", i);
n = n/i;
}
}
// This condition is to handle the case whien n is a prime number
// greater than 2
if (n > 2)
printf ("%ld ", n);
}
/* Driver program to test above function */
int main()
{
long long int n = 600851475143;
primeFactors(n);
return 0;
}
Its very good that you are working on such problems out of class.
Saw your code. You are writing a procedural code inside main function/thread.
Instead write functions and think step by step algorithmically first.
The simple algorithm to solve this problem can be like this:
1) Generate numbers consecutively starting from 2 which is the least prime, to 13195/2. (Any number always has its factor smaller than half of it's value)
2) Check if the generated number is prime.
3) If the number is prime then check if it is factor of 13195;
4) Return the last prime factor as it is going to be the largest prime factor of 13195;
One more advice is try writting seperate functions to avoid code complexity.
Code is like this...
public class LargestPrimeFactor {
public static long getLargestPrimeFactor(long num){
long largestprimefactor = 0;
for(long i = 2; i<=num/2;i++){
if(isPrime(i)){
if(num%i==0){
largestprimefactor = i;
System.out.println(largestprimefactor);
}
}
}
return largestprimefactor;
}
public static boolean isPrime(long num){
boolean prime=false;
int count=0;
for(long i=1;i<=num/2;i++){
if(num%i==0){
count++;
}
if(count==1){
prime = true;
}
else{
prime = false;
}
}
return prime;
}
public static void main(String[] args) {
System.out.println("Largest prime factor of 13195 is "+getLargestPrimeFactor(13195));
}
}

Categories

Resources