Print a prime triangle in JAVA - java

I am trying to print a triangle of 0s and 1s. You get a number N. If N was 5 the triangle should look like:
1
11
111
11101
I get wrong output with 27 for example
1
11
111
11101
11101010
11101010001
11101010001010
11101010001010001
11101010001010001010
Lines ending with non-prime numbers are not printed, the prime numbers are printed as 1s, non-prime as 0s. I have a problem because some lines ending with 0s are printed.
import java.util.Scanner;
public class PrimeTriangle {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner (System.in);
int n = Integer.parseInt(input.nextLine());
boolean isPrime=false;
boolean nums[]=new boolean[n];
for (int i=0; i<=2; i++) {
nums[i]=true;
// System.out.print(nums[i]);
}
for (int i=4; i<=n; i++) {
int m=i/2;
for (int j=2; j<=m; j++) {
if (i%j==0) {
isPrime=false;
break;
}
else {
isPrime=true;
}
}
nums[i-1]=isPrime;
}
char[] digits = new char[n];
for (int i=0; i<n; i++) {
if (nums[i]) {
digits[i]='1';
}
else {
digits[i]='0';
}
}
for (int i=0; i<n; i++) {
if (digits[i]==1) {
System.out.println (new String (digits, 0, i+1));
/*for (int j=0; j<i; j++) {
System.out.print(digits[i]);
}
System.out.println(); */
}
}
}
}

Use Sieve of Eratosthenes to build a char[] of 0's and 1's, then print all substrings ending in 1.
static void printPrimeTriangle(int n) {
char[] primes = new char[n];
Arrays.fill(primes, '1');
for (int sqrt = (int) Math.sqrt(n) + 1, i = 1; i < sqrt; i++)
if (primes[i] == '1')
for (int prime = i + 1, j = prime * 2 - 1; j < n; j += prime)
primes[j] = '0';
for (int i = 0; i < n; i++)
if (primes[i] == '1')
System.out.println(new String(primes, 0, i + 1));
}
Test
printPrimeTriangle(80);
Output
1
11
111
11101
1110101
11101010001
1110101000101
11101010001010001
1110101000101000101
11101010001010001010001
11101010001010001010001000001
1110101000101000101000100000101
1110101000101000101000100000101000001
11101010001010001010001000001010000010001
1110101000101000101000100000101000001000101
11101010001010001010001000001010000010001010001
11101010001010001010001000001010000010001010001000001
11101010001010001010001000001010000010001010001000001000001
1110101000101000101000100000101000001000101000100000100000101
1110101000101000101000100000101000001000101000100000100000101000001
11101010001010001010001000001010000010001010001000001000001010000010001
1110101000101000101000100000101000001000101000100000100000101000001000101
1110101000101000101000100000101000001000101000100000100000101000001000101000001
....:....1....:....2....:....3....:....4....:....5....:....6....:....7....:....8

#kalina199
Here is my approach at it - I was able to reduce it to just one loop :)
package bg.Cholakov;
import java.util.Scanner;
public class PrimeTriangle {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = Integer.parseInt(scanner.nextLine());
int[] array = new int[n];
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0, j = 1; i < n; i++, j++) {
array[i] = j;
if (isPrime(array[i])) {
array[i] = 1;
stringBuilder.append(String.valueOf(array[i]));
System.out.println(stringBuilder);
} else {
array[i] = 0;
stringBuilder.append(String.valueOf(array[i]));
}
}
}
static boolean isPrime(int number) {
for (int i = 2; i <= number / 2; i++) {
if (number % i == 0) {
return false;
}
}
return true;
}
}

Problems in your code:
You have set the value of isPrime to true within the loop. You can not tell if the number is prime until you have divided it with each counter of the loop and found that it is not divisible by any of the loop counters. Therefore, it should be done only when the loop is finished.
In the declaration, for (int i=4; i<=n; i++), you have declared i=4 for the number 5 i.e. you want to set nums[4] to true if 5 is prime or false if 5 is not prime. It means that you want to test 5 (not 4) for the primality. In your code, you have tested 4 for primality.
Given below is the corrected code:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter the limit: ");
int n = Integer.parseInt(input.nextLine());
boolean nums[] = new boolean[n];
for (int i = 0; i <= 2; i++) {
nums[i] = true;
}
for (int i = 3; i < n; i++) {
int num = i + 1, m = num / 2, j;
for (j = 2; j <= m; j++) {
if (num % j == 0) {
nums[i] = false;
break;
}
}
// If j>m, it means that the loop did not terminate because of `break`
if (j > m) {
nums[i] = true;
}
}
// Display nums[] for testing
System.out.println(Arrays.toString(nums));
for (int j = 0; j < n; j++) {
if (nums[j] == false) {
continue;
} else {
for (int i = 0; i <= j; i++) {
if (nums[i] == true) {
System.out.print("1");
} else {
System.out.print("0");
}
}
System.out.println();
}
}
}
}
A sample run:
Enter the limit: 15
[true, true, true, false, true, false, true, false, false, false, true, false, true, false, false]
1
11
111
11101
1110101
11101010001
1110101000101
Additional notes:
I have removed an unnecessary variable, boolean isPrime. The array, boolean nums[] is sufficient in itself. I've also printed nums[] so that you can actually see what values have been set in this array.
A boolean variable has only two values, true and false. Therefore, if you check one value of a boolean variable in if, the else part becomes true for the other value e.g. in the following code, else if (nums[j]==true) is unnecessary and it can simply be written as else.
if (nums[j]==false) {
continue;
} else if (nums[j]==true) {
//...
}
A better approach:
You can make your code much cleaner by using a separate function to determine if a number is prime.
You do not need to check prime by dividing the number by each integer up to half of its value; you just need to divide the number by integers up to its square root. Check this to learn more about it.
Notice how my code looks cleaner by using the ternary operator. Check this to learn more about the ternary operator.
public class Main {
public static void main(String[] args) {
final int N = 5;
StringBuilder sb;
for (int i = 1; i <= N; i++) {
sb = new StringBuilder();
for (int j = 1; j <= i; j++) {
sb.append(j == 1 || isPrime(j) ? 1 : 0);
}
if (sb.charAt(sb.length() - 1) != '0') {
System.out.println(sb);
}
}
}
static boolean isPrime(int n) {
for (int i = 2; i <= Math.sqrt(n); i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
}
Output:
1
11
111
11101
As per your requirement, even though 1 is not a prime number, a 1 should be printed for it. Also, as per this requirement, we do not need to test 0 or a negative integer for primality. Therefore, I have not put any check for 0, or 1 or a negative number in the method, isPrime to keep it clean and just relevant for this requirement.

I created an int array containing 1s and 0s and printed the triangle with two nested for loops. The outer loops is i

Related

Perfect Numbers in an ArrayList

This is an exercise.
A perfect number is a number whose sum of divisors without itself is equal to that number
6 is a perfect number because its divisors are: 1,2,3,6 and 1 + 2 + 3 = 6
28 is a perfect number because its divisors are: 1,2,4,7,28 and 1 + 2 + 4 + 7 = 28
Task: write the body of findNPerfectNumbers, which will find n prime perfect numbers and return them as a list
I must use this program:
import java.util.ArrayList;
public class Exercise {
public static ArrayList<Integer> findNPerfectNumbers(int n)
{
return new ArrayList<>();
}
public static void main(String[] args)
{
System.out.println(findNPerfectNumbers(4));
}
}
I create this code to resolve this problem, but I have a problem to return an ArrayList. I don't know how. It should look like this example: 6 = 1,2,3,6 ///// 28 = 1, 2, 4, 7
My idea:
import java.util.ArrayList;
public class Main
{
public static ArrayList<Integer> findNPerfectNumbers(int n)
{
int sum = 0;
ArrayList<Integer> perfectList = new ArrayList<>();
ArrayList<Integer> factorList = new ArrayList<>();
for (int i = 6; i < n; i++)
{
factorList.clear();
for (int j = 1; j <= i / 2; j++)
{
if (i % j == 0)
{
factorList.add(j);
}
}
sum = 0;
for (int h = 0; h < factorList.size(); h++)
{
sum = sum + factorList.get(h);
}
if (sum == i)
{
perfectList.add(i);
}
}
return perfectList;
}
public static void main(String[] args)
{
System.out.println(findNPerfectNumbers(28));
}
}
Anyone have an idea?
The question is as simple as to have the findNPerfectNumbers function return the first N perfect numbers.
The main part for the exercise is probably to do this as efficiently as possible. For example limiting divider check by half like you do in for (int j = 1; j <= i / 2; j++) is one of many options.
The reason your function doesn't return anything though is because your outer for loop is incorrect with the given input of 4 what you'r doing is for (int i = 6; i < 4; i++) which doesn't do any loops because 4 is smaller than 6.
what you probably intended to do issomething like for (int i = 6; perfectList.size() < n; i++) which would loop aslong as you have fewer than N perfect numbers.
example working code:
import java.util.ArrayList;
public class Exercise {
public static ArrayList<Integer> findNPerfectNumbers(int n) {
int sum = 0;
ArrayList<Integer> perfectList = new ArrayList<>();
for (int i = 6; perfectList.size() < n; i++) {
ArrayList<Integer> factorList = new ArrayList<>();
for (int j = 1; j <= i / 2; j++) {
if (i % j == 0) {
factorList.add(j);
}
}
sum = 0;
for (Integer factor : factorList) {
sum += factor;
}
if (sum == i) {
System.out.println("Found perfect number " + i + " with factors " + factorList);
perfectList.add(i);
}
}
return perfectList;
}
public static void main(String[] args) {
System.out.println(findNPerfectNumbers(4));
}
}
If number is less than 10^1500 you can use Euclid's method
public static List<Long> findPerfect(int n){
List<Long> perfectList=new ArrayList<>();
int x=0;
long sum=0;
long last;
while(perfectList.size()!=n){
last= (long) Math.pow(2,x);
sum+=last;
if(isPrime(sum))
perfectList.add(sum*last);
x++;
}
return perfectList;
}
public static boolean isPrime(long x){
if(x==1)
return false;
for (int i = 2; i <= Math.sqrt(x); i++) {
if(x%i==0)
return false;
}
return true;
}

randomly generate 100 unique numbers using Math.random [duplicate]

my intend is to use simplest java (array and loops) to generate random numbers without duplicate...but the output turns out to be 10 repeating numbers, and I cannot figure out why.
Here is my code:
int[] number = new int[10];
int count = 0;
int num;
while (count < number.length) {
num = r.nextInt(21);
boolean repeat = false;
do {
for (int i=0; i<number.length; i++) {
if (num == number[i]) {
repeat = true;
} else if (num != number[i] && i == count) {
number[count] = num;
count++;
repeat = true;
}
}
} while (!repeat);
}
for (int j = 0; j < number.length; j++) {
System.out.print(number[j] + " ");
}
How about you use a Set instead? If you also want to keep track of the order of insertion you can use a LinkedHashSet.
Random r = new Random();
Set<Integer> uniqueNumbers = new HashSet<>();
while (uniqueNumbers.size()<10){
uniqueNumbers.add(r.nextInt(21));
}
for (Integer i : uniqueNumbers){
System.out.print(i+" ");
}
A Set in java is like an Array or an ArrayList except it handles duplicates for you. It will only add the Integer to the set if it doesn't already exist in the set. The class Set has similar methods to the Array that you can utilize. For example Set.size() is equivalent to the Array.length and Set.add(Integer) is semi-equivalent to Array[index] = value. Sets do not keep track of insertion order so they do not have an index. It is a very powerful tool in Java once you learn about it. ;)
Hope this helps!
You need to break out of the for loop if either of the conditions are met.
int[] number = new int[10];
int count=0;
int num;
Random r = new Random();
while(count<number.length){
num = r.nextInt(21);
boolean repeat=false;
do{
for(int i=0; i<number.length; i++){
if(num==number[i]){
repeat=true;
break;
}
else if(i==count){
number[count]=num;
count++;
repeat=true;
break;
}
}
}while(!repeat);
}
for(int j=0;j<number.length;j++){
System.out.print(number[j]+" ");
}
This will make YOUR code work but #gonzo proposed a better solution.
Your code will break the while loop under the condition: num == number[i].
This means that if the pseudo-generated number is equal to that positions value (the default int in java is 0), then the code will end execution.
On the second conditional, the expression num != number[i] is always true (otherwise the code would have entered the previous if), but, on the first run, when i == count (or i=0, and count=0) the repeat=true breaks the loop, and nothing else would happen, rendering the output something such as
0 0 0 0 0 0...
Try this:
int[] number = new int[10];
java.util.Random r = new java.util.Random();
for(int i=0; i<number.length; i++){
boolean repeat=false;
do{
repeat=false;
int num = r.nextInt(21);
for(int j=0; j<number.length; j++){
if(number[j]==num){
repeat=true;
}
}
if(!repeat) number[i]=num;
}while(repeat);
}
for (int k = 0; k < number.length; k++) {
System.out.print(number[k] + " ");
}
System.out.println();
Test it here.
I believe the problem is much easier to solve. You could use a List to check if the number has been generated or not (uniqueness). Here is a working block of code.
int count=0;
int num;
Random r = new Random();
List<Integer> numbers = new ArrayList<Integer>();
while (count<10) {
num = r.nextInt(21);
if(!numbers.contains(num) ) {
numbers.add(num);
count++;
}
}
for(int j=0;j<10;j++){
System.out.print(numbers.get(j)+" ");
}
}
Let's start with the most simple approach, putting 10 random - potentially duplicated - numbers into an array:
public class NonUniqueRandoms
{
public static void main(String[] args)
{
int[] number = new int[10];
int count = 0;
while (count < number.length) {
// Use ThreadLocalRandom so this is a contained compilable unit
number[count++] = ThreadLocalRandom.current().nextInt(21);
}
for (int j = 0; j < number.length; j++) {
System.out.println(number[j]);
}
}
}
So that gets you most of the way there, the only thing you know have to do is pick a number and check your array:
public class UniqueRandoms
{
public static void main(String[] args)
{
int[] number = new int[10];
int count = 0;
while (count < number.length) {
// Use ThreadLocalRandom so this is a contained compilable unit
int candidate = ThreadLocalRandom.current().nextInt(21);
// Is candidate in our array already?
boolean exists = false;
for (int i = 0; i < count; i++) {
if (number[i] == candidate) {
exists = true;
break;
}
}
// We didn't find it, so we're good to add it to the array
if (!exists) {
number[count++] = candidate;
}
}
for (int j = 0; j < number.length; j++) {
System.out.println(number[j]);
}
}
}
The problem is with your inner 'for' loop. Once the program finds a unique integer, it adds the integer to the array and then increments the count. On the next loop iteration, the new integer will be added again because (num != number[i] && i == count), eventually filling up the array with the same integer. The for loop needs to exit after adding the unique integer the first time.
But if we look at the construction more deeply, we see that the inner for loop is entirely unnecessary.
See the code below.
import java.util.*;
public class RandomDemo {
public static void main( String args[] ){
// create random object
Random r = new Random();
int[] number = new int[10];
int count = 0;
int num;
while (count < number.length) {
num = r.nextInt(21);
boolean repeat = false;
int i=0;
do {
if (num == number[i]) {
repeat = true;
} else if (num != number[i] && i == count) {
number[count] = num;
count++;
repeat = true;
}
i++;
} while (!repeat && i < number.length);
}
for (int j = 0; j < number.length; j++) {
System.out.print(number[j] + " ");
}
}
}
This would be my approach.
import java.util.Random;
public class uniquerandom {
public static void main(String[] args) {
Random rnd = new Random();
int qask[]=new int[10];
int it,i,t=0,in,flag;
for(it=0;;it++)
{
i=rnd.nextInt(11);
flag=0;
for(in=0;in<qask.length;in++)
{
if(i==qask[in])
{
flag=1;
break;
}
}
if(flag!=1)
{
qask[t++]=i;
}
if(t==10)
break;
}
for(it=0;it<qask.length;it++)
System.out.println(qask[it]);
}}
public String pickStringElement(ArrayList list, int... howMany) {
int counter = howMany.length > 0 ? howMany[0] : 1;
String returnString = "";
ArrayList previousVal = new ArrayList()
for (int i = 1; i <= counter; i++) {
Random rand = new Random()
for(int j=1; j <=list.size(); j++){
int newRand = rand.nextInt(list.size())
if (!previousVal.contains(newRand)){
previousVal.add(newRand)
returnString = returnString + (i>1 ? ", " + list.get(newRand) :list.get(newRand))
break
}
}
}
return returnString;
}
Create simple method and call it where you require-
private List<Integer> q_list = new ArrayList<>(); //declare list integer type
private void checkList(int size)
{
position = getRandom(list.size()); //generating random value less than size
if(q_list.contains(position)) { // check if list contains position
checkList(size); /// if it contains call checkList method again
}
else
{
q_list.add(position); // else add the position in the list
playAnimation(tv_questions, 0, list.get(position).getQuestion()); // task you want to perform after getting value
}
}
for getting random value this method is being called-
public static int getRandom(int max){
return (int) (Math.random()*max);
}

Project Euler #49 Java

The question is -
The arithmetic sequence, 1487, 4817, 8147, in which each of the terms
increases by 3330, is unusual in two ways: (i) each of the three terms
are prime, and, (ii) each of the 4-digit numbers are permutations of
one another.
There are no arithmetic sequences made up of three 1-, 2-, or 3-digit
primes, exhibiting this property, but there is one other 4-digit
increasing sequence.
What 12-digit number do you form by concatenating the three terms in
this sequence?
I've written this code -
package Problems;
import java.util.ArrayList;
import java.util.LinkedList;
public class Pro49 {
private static boolean isPrime(int n){
if(n%2 == 0) return false;
for(int i = 3; i<= Math.sqrt(n); i++){
if(n%i == 0) return false;
}
return true;
}
private static boolean isPerm(int m, int n){
ArrayList<Integer> mArr = new ArrayList<>();
ArrayList<Integer> nArr = new ArrayList<>();
for(int i = 0; i<4; i++){
mArr.add(m%10);
m /= 10;
}
for(int i = 0; i<4; i++){
nArr.add(n%10);
n /= 10;
}
return mArr.containsAll(nArr);
}
public static void main(String[] args) {
LinkedList<Integer> primes = new LinkedList<>();
for(int i = 1001; i<10000; i++){
if(isPrime(i)) primes.add(i);
}
int k = 0;
boolean breaker = false;
for(int i = 0; i<primes.size() - 2; i++){
for(int j = i + 1; j<primes.size() - 1; j++){
if(isPerm(primes.get(i), primes.get(j))) {
k = primes.get(j) + (primes.get(j) - primes.get(i));
if(k<10000 && primes.contains(k) && isPerm(primes.get(i), k)) {
System.out.println(primes.get(i) + "\n" + primes.get(j) + "\n" + k);
breaker = true;
break;
}
}
if(breaker) break;
}
if(breaker) break;
}
}
}
I added the print line System.out.println(primes.get(i) + "\n" + primes.get(j) + "\n" + k); to check the numbers. I got 1049, 1499, 1949 which are wrong. (At least 1049 is wrong I guess).
Can any one point out where my code/logic is wrong?
Any help is appreciated.
I think where your logic is going wrong is your isPerm method. You are using AbstractCollection#containsAll, which, AFAIK, only checks if the parameters are in the collection at least once.
i.e. it basically does
for(E e : collection)
if(!this.contains(e)) return false;
return true;
Therefore, for example, 4999 will be a permutation of 49 because 49 contains 4 and 9 (while it is clearly not based on your example).
The reason why your method seems to work for these values is that you are looping a fixed amount of time - that is, 4. For a number like 49 you will end up with {9, 4, 0, 0} instead of {9, 4}. Do something like this:
while(n != 0) {
nArr.add(n%10);
n /= 10;
}
and you will get the correct digit Lists (and see that containsAll won't work.)
Add the 4-digit restriction elsewhere (e.g. in your loop.)
Maybe you could check the occurrences per digit.
For example:
int[] occurrencesA = new int[10], occurrencesB = new int[10];
for(; m != 0; m /= 10)
occurrencesA[m % 10]++;
for(; n != 0; n /= 10)
occurrencesB[n % 10]++;
for(int i = 0; i < 10; i++)
if(occurrencesA[i] != occurrencesB[i]) return false;
return true;
I found a possible alternative for isPerm
private static boolean isPerm(int m, int n){
ArrayList<Integer> mArr = new ArrayList<>();
ArrayList<Integer> nArr = new ArrayList<>();
final String mS = Integer.toString(m);
final String nS = Integer.toString(n);
if(mS.length() != nS.length()) return false;
for(int i = 0; i<mS.length(); i++){
mArr.add(m%10);
m /= 10;
}
for(int i = 0; i<nS.length(); i++){
nArr.add(n%10);
n /= 10;
}
return (mArr.containsAll(nArr) && nArr.containsAll(mArr));
}
This is giving me the correct answer. Another alternative is posted by some other person below.

Function takes a martix (2d array) and prints the max number of the even numbers in each line

I am defining a function to accept a matrix (2d array), for example x[][]; and the function should print the biggest even number in each line
public static void biggestEvenNumOfEachLine(int x[][]){
int even,t=0,max;
int arr[] = new int [x.length];
for(int i = 0; i < x.length;i++){
for(int j = 0; j < x[i].length;j++,t++){
if(x[i][j] % 2 == 0){
even = x[i][j];
arr[j] = even;
}
}
}
}
What am I missing?
I would start by finding the biggest even number in a single line array. Start with the smallest possible value, and then iterate the array. Test for even, and then set the max (and then return it). Something like,
private static int biggestEvenNum(int[] x) {
int max = Integer.MIN_VALUE;
for (int i = 0; i < x.length; i++) {
if (x[i] % 2 == 0) {
max = Math.max(max, x[i]);
}
}
return max;
}
But, in Java 8+, I would prefer to filter for even values and get the max like
private static int biggestEvenNum(int[] x) {
return IntStream.of(x).filter(v -> v % 2 == 0).max().getAsInt();
}
Then your method is as simple as iterating the line(s) in your matrix, printing the result. Like,
public static void biggestEvenNumOfEachLine(int[][] x) {
for (int[] line : x) {
System.out.println(biggestEvenNum(line));
}
}
public static void biggestEvenNumOfEachLine(int x[][])
{
int arr[] = new int [x.length];
for(int i = 0; i < x.length;i++)
for(int j = 0; j < x[i].length;j++)
if(x[i][j] % 2 == 0 && x[i][j] > arr[i]){
arr[i] = x[i][j];
System.out.println(arr[i]);
}
}
This will work but if there is no even number at particular line then corresponding number to that line will be zero.

Prime generating number finder not producing correct output

I'm working on this problem:
Consider the divisors of 30: 1,2,3,5,6,10,15,30.
It can be seen that for every divisor d of 30, d+30/d is prime.
Find the sum of all positive integers n not exceeding 100 000 000
such that for every divisor d of n, d+n/d is prime.
and I thought for sure I had it, but alas, it's apparently giving me the wrong answer (12094504411074).
I am fairly sure my sieve of Eratosthenes is working (but maybe not), so I think the problem is somewhere in my algorithm. It seems to get the right answer for n = 30 (1+2+6+10+22+30 = 71 - is this correct?), but as numbers get larger, it apparently stops working.
Here is my Java code:
import java.util.HashSet;
public class Generators {
static HashSet<Integer> hSet = new HashSet<Integer>();
public static void main(String[] args) {
// TODO Auto-generated method stub
int n = 100000000;
sieveErat(n + 1); //Fill a hashSet with prime numbers
System.out.println("Sieve complete");
int check = 0;
long sum = 3;
for(int i = 2; i <= n; i++){
int numDivisors = 0;
int numPrimeChecks = 0;
boolean done = false;
if(!hSet.contains(i+1)){ //i+1 must be a prime number for i to be prime generating
continue;
}
else{
for(int j = 2; j < i/2; j++){
if(i%j == 0){
numDivisors++;
check = j + i/j;
if(hSet.contains(check)){
done = true;
numPrimeChecks++;
}
}else{
break;
}
}
if(numPrimeChecks == numDivisors && done){
sum += i;
}
}
}
System.out.println(sum);
}
public static void sieveErat(int N){
boolean[] isPrime = new boolean[N + 1];
for (int i = 2; i <= N; i++) {
isPrime[i] = true;
//count++;
}
// mark non-primes <= N using Sieve of Eratosthenes
for (int i = 2; i*i <= N; i++) {
// if i is prime, then mark multiples of i as nonprime
// suffices to consider mutiples i, i+1, ..., N/i
if (isPrime[i]) {
for (int j = i; i*j <= N; j++) {
isPrime[i*j] = false;
// count--;
}
}
}
for(int i = 2; i < isPrime.length; i++){
if(isPrime[i]){
hSet.add(i);
}
}
// System.out.println(count);
}
}
The maths of your sieve looks fine to me. I hacked it around to use a BitSet which is much more space efficient. Is 5761455 primes below 100,000,000 correct?
Once I got your code working I got the same figure you get (12094504411075) what figure should you be getting?
I think this bit is wrong (I have changed the variable names to match the question for clarity)
for(int d = 2; d < Math.sqrt(n+3); d++) {
if (n % d == 0) {
numDivisors++;
int check = d + n / d;
if (primes.get(check)) {
// **** What does done mean??? ****
//done = true;
numPrimeChecks++;
} else {
// **** Added! Got a divisor that did not check. No point in going on.
break;
}
} else {
// **** Why break here??? ****
//break;
}
}
NB I have edited this code to reflect what we finally decided was a correct solution.
Why are you breaking out of the d loop as soon as you hit a d that does not divide n? Surely that cannot be right.
However, I think you can break out of the d loop when you have a divisor that does not check.
Also, what is your intended functionality of done? It seems to have no real function.
And, why do you start sum at 3?
Removing the break I now get the value 1739023853139. Is this correct?
Added
Here's my sieve. Identical to yours but builds a BitSet which is a much more efficient structure than a HashSet in this case:
public static BitSet sieveOfEratosthenes(int n) {
BitSet isPrime = new BitSet(n);
// Iniially all numbers are prime.
for (int i = 2; i <= n; i++) {
isPrime.set(i);
}
// mark non-primes <= N using Sieve of Eratosthenes
for (int i = 2; i * i <= n; i++) {
// if i is prime, then mark multiples of i as nonprime
// suffices to consider mutiples i, i+1, ..., N/i
if (isPrime.get(i)) {
for (int j = i; i * j <= n; j++) {
isPrime.clear(i * j);
}
}
}
//System.out.println("Found " + isPrime.cardinality() + " primes");
return isPrime;
}

Categories