Algorithm: List all prime number using Sieve of Eratosthenes - java

I have implemented Sieve of Eratosthenes for finding the list of prime number from 1 to n. My code is working fine for inputs from 1 to 10,000 but I am getting following for values >100,000:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -2146737495
at SieveOfEratosthenes.main(SieveOfEratosthenes.java:53)
I am able to find the issue, which is in the for loop when I am doing i * i as it is going out of Integer range (Integer.MAX_VALUE), but I could not find the solution. Can someone suggest me what changes can be done also I appreciate if someone suggest me any improvement for efficiency in this implementation?
public class SieveOfEratosthenes {
public static void main(String[] args) {
Integer num = Integer.parseInt(args[0]);
Node[] nodes = new Node[num + 1];
for(int i = 1; i < nodes.length; i++) {
Node n = new Node();
n.setValue(i);
n.setMarker(true);
nodes[i] = n;
}
for(int i = 1; i < nodes.length; i++) {
if(nodes[i].getMarker() && nodes[i].getValue() > 1) {
System.out.println("Prime " + nodes[i].getValue());
} else {
continue;
}
for(int j = i * i; j < nodes.length
&& nodes[i].getMarker(); j = j + i) {
nodes[j].setMarker(false);
}
}
System.out.println(l.size());
}
}
class Node {
private int value;
private boolean marker;
public void setValue(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
public void setMarker(boolean marker) {
this.marker = marker;
}
public boolean getMarker() {
return this.marker;
}
public String toString() {
return ("Value : " + marker + " value " + value);
}
}

Essentially, the for(int j = i * i;... loop is to cross out all multiples of i.
It makes sense only to cross out starting from i * i, since all lesser multiples are already crossed out by their lesser divisors.
There are at least two ways to go from here.
First, you can start crossing out from i * 2 instead of i * i.
This will get rid of the overflow.
On the bad side, the complexity of the sieve would grow from O(n log log n) to O(n log n) then.
Second, you can check whether i * i is already too much, and if it is, skip the loop completely.
Recall that it is essentially skipped anyway for i greater than the square root of nodes.length if no overflow occurs.
For example, just add an if (i * 1L * i < nodes.length) before the loop.

for(int i = 1; i < nodes.length; i++) {
if(nodes[i].getMarker() && nodes[i].getValue() > 1) {
System.out.println("Prime " + nodes[i].getValue());
} else {
continue;
}
TO
int limit = 2 << 14;
for(int i = 1; i < nodes.length; i++) {
if(nodes[i].getMarker() && nodes[i].getValue() > 1 && i <= 2 << 15) {
System.out.println("Prime " + nodes[i].getValue());
if (i > limit) {
continue;
}
} else {
continue;
}

Related

Calculating primes with long (Java)

I want to write a little program which is able to find the first 10 digit long prime number out of the euler number.
The number on the 99th place is the number I am searching for, but the isPrim() method does not respond correctly. Do you see what went wrong?
My Code
public class Main {
public static final String e = "27182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966";
public static void main(String[] args) {
System.out.println(e);
for (int i = 0; i < e.length() - 10; i++) {
String str = e.substring(i, i + 10);
long num = Long.parseLong(str);
boolean isPrim = isPrim(num);
if (isPrim == true) {
System.out.println("First prime: " + num);
break;
}
System.out.println(i + " " + str + " " + isPrim);
}
}
public static boolean isPrim(long number) {
if (number % 2 == 0) {
return false;
}
for (int j = 3; j * j < number; j+=2) {
if (number % j == 0) {
return false;
}
}
return true;
}
}
Should be j * j <= number, otherwise you will treat squares of primes as primes. I.e. your method says that 9 is prime, because there are no dividers less than sqrt(9).
Also, your code will probably find prime that is shorter than 10 digits, because it checks all 10-digits substrings of E, including those with leading zeros, such as 0452353602.
Also, you need to change type of j to long to avoid overflow.

Bin Packing(Searched quad groups for answers)

I am writing a bin packing program in one dimension. I want only one possible bin. So it does not include a lot of bin its only one. This program is only searching quad groups and explode if quad groups are not equal to the searching number. I want to search every possible group that is bigger than quads.
In example we have 60 60 50 40 45 35 25 15 and we are looking for summing equal to 180 and answer is 60 60 45 15 that's fine but if we search 250 it will not working.
Can you help me?
That's the link for program https://github.com/omerbguclu/BinPacking1D
That's the code for the algorithm o array is the numbers, a array is the location of answers
public BinPacking() {
}
public void binpack(ArrayList<Integer> o, ArrayList<Integer> a, int wanted) {
int sum = 0;
if (wanted > 0) {
control(o, a, wanted);
if (is) {
return;
}
for (int i = 0; i < o.size(); i++) {
sum += o.get(i);
summing(o, a, wanted - sum, i + 1);
if (is) {
a.add(i);
return;
}
for (int j = i; j < o.size(); j++) {
if (i != j) {
sum += o.get(j);
summing(o, a, wanted - sum, j + 1);
if (is) {
a.add(i);
a.add(j);
return;
}
sum -= o.get(j);
}
}
sum -= o.get(i);
// "/////////////*******************////////////////////");
}
if (wanted != sum) {
System.out.println("There is not an answer with quad summing method");
}
}
}
public void summing(ArrayList<Integer> o, ArrayList<Integer> a, int wanted, int loop) {
int sum = 0;
if (loop < o.size() && wanted > 0) {
for (int i = loop; i < o.size(); i++) {
if (wanted == o.get(i)) {
a.add(i);
is = true;
return;
}
for (int j = loop; j < o.size(); j++) {
if (i != j) {
sum = o.get(i) + o.get(j);
if (wanted != sum) {
sum = 0;
} else {
a.add(i);
a.add(j);
is = true;
return;
}
}
// System.out.println("///////////////////////////////////");
}
}
System.out.println("There is not an answer with binary summing method");
}
}
public void control(ArrayList<Integer> o, ArrayList<Integer> a, int wanted) {
for (int i = 0; i < o.size(); i++) {
if (o.get(i) == wanted) {
a.add(i);
is = true;
break;
}
}
}
There is a pretty well established and efficient mechanism for getting every possible combination of a set of objects. Essentially you treat membership of the combination as a BitSet which represents whether each member of the set is in the combination. Then visiting every combination is just visiting every BitSet combination.
Here's how I tend to implement it:
public class Combo<T> implements Iterable<List<T>> {
private final List<T> set;
public Combo(List<T> set) {
this.set = set;
}
public Iterator<List<T>> iterator() {
BitSet combo = new BitSet(set.size());
return new Iterator<List<T>>() {
public boolean hasNext() {
return combo.cardinality() < set.size();
}
public List<T> next() {
int i = 0;
while (combo.get(i))
combo.clear(i++);
combo.set(i);
return combo.stream().mapToObj(set::get).collect(Collectors.toList());
}
};
}
}
So your solution would become:
for (List<Integer> combo: new Combo<>(...)) {
if (combo.size >= 4 && combo.stream.reduce(0, Integer::sum) == total)
....
}
A hackier version of the same idea would be:
for (long l = 0; l < 1 << (input.size() - 1); l++) {
List<Integer> combo = BitSet.valueOf(new long[]{l}).stream()
.mapToObj(input::get).collect(Collectors.toList());
if (combo.stream().mapToInt(n -> n).sum() == total) {
System.out.println(combo);
}
}

Count number of Divisors for all the numbers till N

I need to count all the divisors for every number in the range 1 to n. I have written down below an implementation for, given an integer num, it counts the number of divisors of num. Its complexity is O(sqrt(n)). So over all complexity comes out to be O(n * sqrt(n)). Can it be reduced? If YES, then can you give an algorithm for that?
CODE :
public static int countDivisors(int num)
{
int limit = (int)Math.sqrt(num);
int count = 2;
for(int i = 2 ; i <= limit ; i++)
{
if(num % i == 0)
{
count++;
if(num / i != i)
{
count++;
}
}
}
return count;
}
PS:
This function will be called n times.
You can improve upon the naive approach using kind of a generalized Sieve of Eratosthenes. Instead of just marking the number as composite also store its first divisor that you found (I do this in the function computeDivs below).
class Main
{
// using Sieve of Eratosthenes to factorize all numbers
public static int[] computeDivs(int size) {
int[] divs = new int[size + 1];
for (int i = 0; i < size + 1; ++i) {
divs[i] = 1;
}
int o = (int)Math.sqrt((double)size);
for (int i = 2; i <= size; i += 2) {
divs[i] = 2;
}
for (int i = 3; i <= size; i += 2) {
if (divs[i] != 1) {
continue;
}
divs[i] = i;
if (i <= o) {
for (int j = i * i; j < size; j += 2 * i) {
divs[j] = i;
}
}
}
return divs;
}
// Counting the divisors using the standard fomula
public static int countDivisors(int x, int[] divs) {
int result = 1;
int currentDivisor = divs[x];
int currentCount = 1;
while (currentDivisor != 1) {
x /= currentDivisor;
int newDivisor = divs[x];
if (newDivisor != currentDivisor) {
result *= currentCount + 1;
currentDivisor = newDivisor;
currentCount = 1;
} else {
currentCount++;
}
}
if (x != 1) {
result *= currentCount + 1;
}
return result;
}
public static int countAllDivisors(int upTo) {
int[] divs = computeDivs(upTo + 1);
int result = 0;
for (int i = 1; i <= upTo; ++i) {
result += countDivisors(i, divs);
}
return result;
}
public static void main (String[] args) throws java.lang.Exception {
System.out.println(countAllDivisors(15));
}
}
You can also see the code executed on ideone here.
In short I use the sieve to compute the biggest prime factor for each number. Using this I can compute the factor decomposition of every number very efficiently (and I use this in countDivisors).
It is hard to compute the complexity of the sieve but a standard estimate is O(n * log(n)). Also I am pretty confident it is not possible to improve on that complexity.
You can do much better than O(n.sqrt(n)) by using simple iteration. The code is in C++, but you can easily get the idea.
#include <iostream>
#include <vector>
using namespace std;
void CountDivisors(int n) {
vector<int> cnts(n + 1, 1);
for (int i = 2; i <= n; ++i) {
for (int j = i; j <= n; j += i) {
cnts[j]++;
}
}
for (int i = 1; i <= n; ++i) {
cout << cnts[i] << " \n"[i == n];
}
}
int main() {
CountDivisors(100);
return 0;
}
Running time is n/1 + n/2 + n/3 + n/4 + ... + n/n which can be approximated by O(nH(n)), where H(n) is the harmonic series. I think the value is not bigger than O(nlog(n)).
Using iteration is OK for relatively small numbers. As soon as the number of divisors is getting bigger (over 100-200), the iteration is going to take a significant amount of time.
A better approach would be to count the number of divisors with help of prime factorization of the number.
So, express the number with prime factorization like this:
public static List<Integer> primeFactorizationOfTheNumber(long number) {
List<Integer> primes = new ArrayList<>();
var remainder = number;
var prime = 2;
while (remainder != 1) {
if (remainder % prime == 0) {
primes.add(prime);
remainder = remainder / prime;
} else {
prime++;
}
}
return primes;
}
Next, given the prime factorization, express it in the exponent form, get exponents and add 1 to each of them. Next, multiply resulting numbers. The result will be the count of divisors of a number. More on this here.
private long numberOfDivisorsForNumber(long number) {
var exponentsOfPrimeFactorization = primeFactorizationOfTheNumber(number)
.stream()
.collect(Collectors.groupingBy(Integer::intValue, Collectors.counting()))
.values();
return exponentsOfPrimeFactorization.stream().map(n -> n + 1).reduce(1L, Math::multiplyExact);
}
This algorithm works very fast. For me, it finds a number with 500 divisors within less than a second.

How would these methods be setup to increment and decrement the last number in an array by 1? Java

For this project I am creating arrays, each with 50 elements, each element with a value between 0 and 9, and using those arrays called "BigIntegers" in addition, subtraction, multiplication and division. There are a few smaller methods called increment and decrement that I am having trouble figuring out. This is the code that I have done...
public class BigInteger {
int[] BigInteger = new int[50];
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//x BigInteger(): creates a BigInteger of all 0's x
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
public BigInteger() {
for (int i = 0; i < 50; i++) {
BigInteger[i] = 0;
}
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//x BigInteger(n): creates a BigInteger the size of n x
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
public BigInteger(int n) {
for (int i = 49; i > 0; i--) {
BigInteger[i] = n%10;
n = n/10;
}
BigInteger[0] = n;
}
public int[] getBigInteger() {
return BigInteger;
}
public BigInteger(BigInteger n) {
for(int i = 0; i < 50; i++) {
BigInteger[i] = n.getBigInteger()[i];
}
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//x print(): prints out each element of the BigInteger array x
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
public void print() {
int index = 0;
for (int i = 0; i < BigInteger.length; i++) {
if (BigInteger[i] == 0) { index = 0; }
else { index = i; break; }
}
for(int i = index; i < BigInteger.length; i++) {
System.out.print(BigInteger[i] + " ");
}
}
public void decrement() {
int last = BigInteger.length;
for(int i = last; i < 50; i++) {
if (i == 0) { }
else last = BigInteger[last] - 1;
}
}
public static void main(String args[]) {
BigInteger big = new BigInteger(50);
BigInteger big2 = new BigInteger();
BigInteger big3 = new BigInteger(602345812);
}
The functions of these methods are:
• void increment( ) --- increase the value of the invoking object by 1
• void decrement( ) --- decrement the value of the invoking object by 1
I've spent numerous hours trying to figure out these, what seem to be, easy methods. Any help or advice?
Thanks I.
If I understand your question well, you should try this (with remarks from #Andy Turner and #Yang Li) as a starting point:
public void increment() {
for (int i = BigInteger.length - 1; i; i--)
if (BigInteger[i] < 9) {
BigInteger[i]++;
for (int j = i + 1; j < BigInteger.length; j++)
BigInteger[j] = 0;
break;
}
else if (i == 0)
// cannot increment 9
}
public void decrement() {
for (int i = BigInteger.length - 1; i; i--)
if (BigInteger[i] > 0) {
BigInteger[i]--;
for (int j = i + 1; j < BigInteger.length; j++)
BigInteger[j] = 9;
break;
}
else if (i == 0)
// cannot decrement 0
}
This will increment / decrement the last int element of your BigInteger array, where BigInteger.length - 1 is the index of the last element in your array.
There are already some answers by this post, but you need to be careful because some of these answers don't deal with overflow. If the last digit is 9 and you increment it by 1, it will overflow, if the last digit is 0 and you subtract, it will also be problematic.
You should also consider the case where all the digits in your BigInteger array are '9'. In this case if you increment it by one, no more rooms would be allowed in your array. Same thing may happen if all the digits in BigInteger are '0' and you want to subtract it by 1. For those cases you should probably throw an error.
Update
I have implemented the recursive way to increment the big integer.
Please note that I have handled the case where all digits in BigInteger are '9'. You should check if this input is expected, otherwise you should remove this check.
public void increment() {
increment(BigInteger.length-1);
}
private void increment(int index) {
if (index < 0) {
throw new RuntimeException("BigInteger maximum capacity reached!");
}
if (BigInteger[index] < 9) {
BigInteger[index]++;
} else {
BigInteger[index] = 0;
increment(--index);
}
}
Basically this will keep looking for leading digits until it is less than 9 and then increment that digit, during the process it will set any '9' it encounters to '0'.
I didn't implement the "decrease" method because I think it would be good that you can come up with your own solution.

Lychrel Number Program Error

I am trying to make the lychrel number program. but i cannot make it. Criteria is that, list the Lychrel Number which is below in 10000,Lychrel number checking iteration in limited. I have been set it as 30.But i didnt got the solution yet.
number should be listed if the checking completed upto 30 iteration. i didnt get the solutions.help me.
public class LychrelNumber {
static final int MAX_NUMBER = 10000;
static final int MAX_ITERATION = 30;
int iterationCount = 0;
void listTheLychrelNymber() throws Exception {
long i = 0;
long temp;
for (int j = 0; j < MAX_NUMBER; j++) {
iterationCount = 0;
temp = j;
for (i = 0; i < MAX_ITERATION; i++) {
long first = temp;
long second = reverseTheNumber(temp);
long third = first + second;
long fourth = reverseTheNumber(third);
if (third == fourth) {
break;
} else {
temp = third;
if (i == MAX_ITERATION) {
System.out.println("Lychrel Numbers are :" + j);
}
}
}
}
}
long reverseTheNumber(long n) {
long reverse = 0;
while (n != 0) {
reverse = reverse * 10;
reverse = reverse + n % 10;
n = n / 10;
}
return reverse;
}
public static void main(String[] args) {
try {
LychrelNumber lychrelNumber = new LychrelNumber();
lychrelNumber.listTheLychrelNymber();
} catch (Exception e) {
}
}
}
it is build successfull. but i didnt get the output.
Look at your loop of i (I shortened the code a bit)
for (i = 0; i < MAX_ITERATION; i++) {
if (i == MAX_ITERATION) {
System.out.println("Lychrel Numbers are :" + j);
}
}
As you see, you stop looping when i reaches MAX_ITERATION but only print the Lychrel number in the loop if i == MAX_ITERATION (which will of course never happen).
I got the solution.
if (i == (MAX_ITERATION-1)) {
System.out.println("Lychrel Numbers are:" + j);
}
here i made the mistake in Condition Checking..

Categories

Resources