I tried it several times but still gives me ArrayOutOfIndex. But i want to save the memory so i use
boolean[]isPrime = new boolean [N/2+1];
instead of
boolean[]isPrime = new boolean [N+1];
This gives me ArrayOutOfIndex for line 23 and 47
line 23:
for (int i = 3; i <= N; i=i+2) {
isPrime[i] = true;
}
line 47:
for (int i = 3; i <= N; i=i+2) {
if (isPrime[i]) primes++;
...
}
Full code:
public class PrimeSieve {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java PrimeSieve N [-s(ilent)]");
System.exit(0);
}
int N = Integer.parseInt(args[0]);
// initially assume all odd integers are prime
boolean[]isPrime = new boolean [N/2+1];
isPrime[2] = true;
for (int i = 3; i <= N; i=i+2) {
isPrime[i] = true;
}
int tripCount = 0;
// mark non-primes <= N using Sieve of Eratosthenes
for (int i = 3; i * i <= N; i=i+2) {
// if i is prime, then mark multiples of i as nonprime
if (isPrime[i]) {
int j = i * i;
while (j <= N){
tripCount++;
isPrime[j] = false;
j = j + 2*i;
}
}
}
System.out.println("Number of times in the inner loop: " + tripCount);
// count and display primes
int primes = 0;
if(N >= 2 ){
primes = 1;
}
for (int i = 3; i <= N; i=i+2) {
if (isPrime[i]) primes++;
if (args.length == 2 && args[1].equals("-s"))
; // do nothing
else
System.out.print(i + " ");
}
System.out.println("The number of primes <= " + N + " is " + primes);
}
}
You should store and access the array using the same indexing function: isPrime[i/2]
When you change the size of your array from [N+1] to [N/2+1], you need to also update the end-conditions of your for-loops. Right now your for-loops run until i=N, so you are trying to do isPrime[i] when i > (N/2+1) ... so you get an ArrayIndexOutOfBoundsException.
Change this:
for (int i = 3; i <= N; i=i+2)
to this:
for (int i = 3; i <= N/2; i=i+2)
Well, for example if N=50 your isPrime only holds 26 elements, and you're trying to access the elements at 3,5..47,49 (which, of course, is out of bounds)
What you probably want is to use i/2 (as the index) inside your loops, that way you are still iterating over the numbers 3,5..47,49, but you use the correct indexes of your vector.
Related
I'm doing this program: Given an integer, n, if the sum of its divisors (not counting itself) equals n, that number is said to be perfect. If the sum is lower, it is said to be decient, and if it is higher it is said to be abundant. For example:
6 has divisors 1,2,3: they add 6, therefore 6 is perfect. 8 has divisors 1,2,4: they add 7, therefore 8 is deciente. 24 has divisors 1,2,3,4,6,8,12: they add 36, therefore 24 is abundant.
Write a program that reads two positive integers and displays, on the screen, how many numbers there are of each type in that interval (including the extremes).
I have the following code and I know where it fails, for example if I enter a single number, I do it well, example of entries 6 and 7. If I then enter 6 and 9 the output is Perfect 1 Deficient 0 Abundant 2, when I should to be Perfect 1 Deficient 2 Abundant 0. Variable j stores the divisors of all in the variable j and then that's why it's abundant but I have not been able to correct it for more than I've tried.
import java.util.Scanner;
public class PerfectNumbers {
public static void main(String[] args) {
System.out.println("Enter two numbers for the interval:");
Scanner teclado = new Scanner(System.in);
int x = teclado.nextInt();
int y = teclado.nextInt();
int cont1 = 0;
int perfect = 0;
int deficient = 0;
int abundant = 0;
for (int i = x; i < y; i++) {
for (int j = 1; j < i; j++) {
if (i % j == 0) {
cont1 += j;
} else {
cont1 += 0;
}
}
if (cont1 == x) {
perfect += 1;
} else if (cont1 < x) {
deficient += 1;
} else if (cont1 > x) {
abundant += 1;
}
}
System.out.println("Perfect"+ perfect);
System.out.println("Deficient"+ deficient);
System.out.println("Abundant"+ abundant);
}
}
One problem is that you didn't reset cont1.
Another problem is that instead of comparing to x to decide perfect/deficient/abundant, you need to compare to i.
for (int i = x; i < y; i++) {
cont1 = 0;
for (int j = 1; j < i; j++) {
if (i % j == 0) {
cont1 += j;
}
}
if (cont1 == i) {
perfect += 1;
} else if (cont1 < i) {
deficient += 1;
} else {
abundant += 1;
}
}
I think the second problem was easy to overlook because of the poor naming of variables. I suggest to improve that, and it will be easier to read and harder to make such mistakes:
for (int n = start; n < end; n++) {
sum = 0;
for (int j = 1; j < n; j++) {
if (n % j == 0) {
sum += j;
}
}
if (sum == n) {
perfect++;
} else if (sum < n) {
deficient++;
} else {
abundant++;
}
}
I am supposed to create a perfect number class using the following pseudocode:
For i from 2 to “very large”,
For j from 2 to √i,
if (j evenly divides i),
accumulate the sum j and i/j
if √i is an integer
subtract √i ... you added it twice
if the sum of divisors == i
Print the number ... it’s perfect!
So here is my version. It runs, but it doesn't do what I want at all. It just runs and produces nothing as an output. Can someone tell me what is wrong with my program? It's bothering me so much.
import java.util.Scanner;
public class PerfectNumber {
public static void main(String[] args) {
double sum = 0
double newsum = 0;
for (int i = 2; i < 1000000; i++) {
for (int j = 2; i<Math.sqrt(i); j++){
if (i%j==0){
sum = j + (i%j);
}
if (Math.sqrt(i)==(int)i){
newsum = sum - Math.sqrt(i);
}
if (sum == 0) {
System.out.println(sum + "is a perfect number");
}
}
}
}
}
Few mistakes according to the algorithm:
sum = j + (i%j); should be changed to sum = j + (i/j);
This piece:
if (Math.sqrt(i)==(int)i){
newsum = sum - Math.sqrt(i);
}
if (sum == 0) {
System.out.println(sum + "is a prime number");
}
Should be under upper "for"
Math.sqrt(i)==(int)i would never be true unless i is 1. If you want to check this that way you should write Math.sqrt(i)==((int) Math.sqrt(i))
There are much more errors, the simplest way to do it is:
double sum = 0;
for (int i = 1; i <= 10000; i++) {
for (int j = 1; j < i; j++) {
if (i % j == 0) {
sum += j;
}
}
if (i == sum) {
System.out.println(sum + " is a prime number");
}
sum = 0;
}
Your code contains several mistakes. Here is the corrected code, commented with the changes.
// newsum isn't needed; declare sum to be int to avoid floating-point errors
int sum = 0;
for (int i = 2; i < 1000000; i++) {
// Start with 1; every natural number has 1 as a factor.
sum = 1;
// Test if j, not i, is less than the square root of i.
for (int j = 2; j <= Math.sqrt(i); j++){
if (i % j == 0){
// Add to sum; don't replace sum. Use i / j instead of i % j.
sum = sum + j + (i / j);
// Move test inside this if; test if j is square root of i
if (j*j == i){
// I used j because we know it's the square root already.
sum = sum - j;
}
}
// Move print outside of inner for loop to prevent multiple
// printings of a number.
// Test if sum equals the number being tested, not 0.
if (sum == i) {
// Space before is
System.out.println(sum + " is a perfect number");
}
}
}
Output:
6 is a perfect number
28 is a perfect number
496 is a perfect number
8128 is a perfect number
public static void main(String[] args){
int min = 2;
int max = 1000000;
int sum = 0;
for (; min <= max; min++,sum = 0) {
for (int e = 1; e < min; e++)
sum += ((min % e) == 0) ? e : 0;
if (sum == min){
System.out.println(sum);
}
}
}
for(n=1;n<=number;n++){ //calculates the sum of the number.
int i=1;
int sum = 0;
while(i<n){
if(n%i==0)
sum+=i;
i++;
}
if(sum==n){ //if the sum is equal to its sum :
System.out.print(n+": ");
for (int j = 1;j<n;j++){
if(n%j==0){
System.out.print(j+" ");
}
}
System.out.println();
}
}
Here is the simplest and easiest form you can write a program for perfect number....this code gives perfect number within 25 ...you can change as you want
import java.util.Scanner;
public class PerfectNumber {
public static void main(String[] args) {
int n,i,j,count=0;
for(i=2;i<=25;i++) {
for(j=1;j<=i;j++) {
if(i%j ==0) /*count increments if a reminder zero*/ {
count++;
}
}
/*since a perfect number is divided only by 1 and itself
if the count is 2 then its a prime number...*/
if(count==2)
System.out.println(i);
count=0;
}
return 0;
}
}
According to the pseudocode you want to move the second and third if test outside of the inner loop
for (int i = 2; i < 1000000; i++) {
double iroot = Math.sqrt(i);
int sum = 1;
for (int j = 2; j <= iroot; j++){
if (i % j == 0){
sum = sum + j + i / j;
}
}
if (iroot == (int) iroot) {
sum = sum - iroot;
}
if (sum == i) {
System.out.println(sum + "is a perfect number");
}
}
Thanks for watched
public boolean testPerfect(int n){
int i=1;
int sum=0;
while(i<n){
if(n%i==0)
{
sum+=i++;
}
else{
i++;}
}
if (sum==n){
return true;
}
return false;
}
Note: no mapping, no sorting
Here's my code:
public static void countArray(int[] n){
int[] m = new int[n.length]; //50 elements of integers between values of 10 & 20
int count = 0;
int sum = 0;
for ( int i = 0; i < n.length ; i++){
m[i] = n[i]; //make a copy of array 'n'
System.out.print(m[i]+" ");
}System.out.println();
for ( int j =0; j < n.length ; j++){
count =0;
for(int i = 0; i < n.length ; i++){
if (n[j]%m[i]==0 && n[j] == m[i])
count++;
}if ( n[j]%m[j] == 0)
System.out.println(m[j] + " occurs = " + count);
}
}
So the problem is: I get repeating results like : "25 occurs = 5", on different lines.
What I think: the problem occurs because of if ( n[j]%m[j] == 0)
so I tried if ( n[j]%m[j+1] == 0). Another problem occurs since m[j] will be m[50] so it crashes but sort of give me the results that I want.
Result that I want: something like this: no repetitions and covers all the random integers on a set
17 occurs = 3
23 occurs = 2
19 occurs = 3
15 occurs = 2
12 occurs = 2
With some adaptation your code should work :
public static void countArray(int[] n){
boolean [] alreadyCounted = new boolean[n.length];
for (int i = 0; i < n.length ; i++){
int count = 0;
if (alreadyCounted[i]) {
// skip this one, already counted
continue;
}
for(int j = 0; j < n.length ; j++){
if (n[i] == n[j]) {
// mark as already counted
alreadyCounted[j] = true;
count++;
}
}
System.out.println(n[i] + " occurs = " + count);
}
}
You could definitely use the same logic with better code, I just tried to follow the original "coding style";
This is O(n^2) solution (read "very slow").
If you could use sorting, you could do it in O(n log(n)) - that is fast.
With mapping you could do it in O(n) - that is blazingly fast;
If you exploit the input limit you can lose the nested loop:
public static void main(String[] args)
{
//6 elements of integers between values of 10 & 20
int[] countMe = { 10, 10, 20, 10, 20, 15 };
countArray(countMe);
}
/** Count integers between values of 10 & 20 (inclusive) */
public static void countArray(int[] input)
{
final int LOWEST = 10;
final int HIGHEST = 20;
//Will allow indexes from 0 to 20 but only using 10 to 20
int[] count = new int[HIGHEST + 1];
for(int i = 0; i < input.length; i++)
{
//Complain properly if given bad input
if (input[i] < LOWEST || HIGHEST < input[i])
{
throw new IllegalArgumentException("All integers must be between " +
LOWEST + " and " + HIGHEST + ", inclusive");
}
//count
int numberFound = input[i];
count[numberFound] += 1;
}
for(int i = LOWEST; i <= HIGHEST; i++)
{
if (count[i] != 0)
{
System.out.println(i + " occurs = " + count[i]);
}
}
}
try this :(sort the array and then count the occurence of element)
public static void countArray(int[] n) {
int count = 0;
int i, j, t;
for (i = 0; i < n.length - 1; i++) // sort the array
{
for (j = i + 1; j < n.length; j++) {
if (n[i] > n[j]) {
t = n[i];
n[i] = n[j];
n[j] = t;
}
}
}
for (i = 0; i < n.length;)
{
for (j = i; j < n.length; j++) {
if (n[i] == n[j])
{
count++;
} else
break;
}
System.out.println(n[i] + " occurs " + count);
count = 0;
i = j;
}
}
Here's a nice, efficient way to do it, rather more efficiently than the other solutions posted here. This one runs in O(n) time, where the array is of length n. It assumes that you have some number MAX_VAL, representing the maximum value that you might find in your array, and that the minimum is 0. In your commenting you suggest that MAX_VAL==20.
public static void countOccurrences(int[] arr) {
int[] counts = new int[MAX_VAL+1];
//first we work out the count for each one
for (int i: arr)
counts[i]++;
//now we print the results
for (int i: arr)
if (counts[i]>0) {
System.out.println(i+" occurs "+counts[i]+" times");
//now set this count to zero so we won't get duplicates
counts[i]=0;
}
}
It first loops through the array increasing the relevant counter each time it finds an element. Then it goes back through, and prints out the count for each one. But, crucially, each time it prints the count for an integer, it resets that one's count to 0, so that it won't get printed again.
If you don't like the for (int i: arr) style, this is exactly equivalent:
public static void countOccurrences(int[] arr) {
int[] counts = new int[MAX_VAL+1];
//first we work out the count for each one
for (int i=0; i<arr.length; i++)
counts[arr[i]]++;
//now we print the results
for (int i=0; i<arr.length; i++)
if (counts[arr[i]]>0) {
System.out.println(arr[i]+" occurs "+counts[arr[i]]+" times");
//now set this count to zero so we won't get duplicates
counts[arr[i]]=0;
}
}
I have the following code which spits out prime numbers between 1 and N. A friend came up with this solution but I believe there is a more efficient way to write this code. Such as making it so that if (i%j!=0) {System.out.print (i + " ");}. However I found this spat out numbers randomly all over the place...
import java.util.Scanner;
public class AllPrime {
public static void main(String[] args) {
System.out.println("Enter a number:\n");
Scanner input = new Scanner(System.in);
int a = input.nextInt();
for (int i = 2; i < a; i++) {
boolean primeNum = true;
for(int j=2; j<i; j++) {
if (i%j==0) {
primeNum =false;
}
}
if (primeNum) {
System.out.print(i + " ");
}
}
}
}
Look at proper sieves, like the Sieve of Eratosthenes. You don't need to be checking for % each time.
for(int j=2; j<i; j++) {
if (i%j==0) {
primeNum =false;
}
}
This is not a very efficient algorithm, but at the very least, put a break in there...
public static boolean [] createPrimes (final int MAX)
{
boolean [] primes = new boolean [MAX];
// Make only odd numbers kandidates...
for (int i = 3; i < MAX; i+=2)
{
primes[i] = true;
}
// ... except No. 2
primes[2] = true;
for (int i = 3; i < MAX; i+=2)
{
/*
If a number z is already eliminated
(like No. 9), because it is a multiple of -
for example 3, then all multiples of z
are already eliminated.
*/
if (primes[i] && i < MAX/i)
{
int j = i * i;
while (j < MAX)
{
if (primes[j])
primes[j] = false;
j+=2*i;
}
}
}
return primes;
}
updated after comment of Will Ness:
Improves the speed to about 2/1, it checks 100 Million ints in 5s on my 2Ghz single core.
private static void generatePrimes(int maxNum) {
boolean[] isPrime = new boolean[maxNum + 1];
for (int i = 2; i <= maxNum; i++)
isPrime[i] = true;
// mark non-primes <= N using Sieve of Eratosthenes
for (int i = 2; i * i <= Math.sqrt(maxNum); i++) {
// if i is prime, then mark multiples of i as nonprime
if (isPrime[i]) {
for (int j = i; i * j <= maxNum; j++)
isPrime[i * j] = false;
}
}
// count primes
int primes = 0;
for (int i = 2; i <= maxNum; i++)
if (isPrime[i]) {
System.out.println("Prime - " + i);
primes++;
}
System.out.println("The number of primes <= " + maxNum + " is "+ primes);
}
I am new here. I am trying to solve this exercise Problem 18 just for reinforcing my solving skills. I've already coded the answer. The task asks for "How many of the primes below 1,000,000 have the sum of their digits equal to the number of days in a fortnight?" (a fortnight is 14 days). My answers is 16708, but it is wrong. I hope you can help me. I don't know what my error is. I have 2 methods, 1 for generating the primes, and another for counting the digits of each prime.
This is my code:
import java.util.ArrayList;
import java.util.List;
public class Problema18 {
public static void main(String args[]) {
ArrayList<Integer> num = primes();
System.out.println(num);
count(primes());
}
public static ArrayList<Integer> primes() {
List<Integer> primes = new ArrayList<Integer>();
primes.add(2);
for (int i = 3; i <= 1000000; i += 2) {
boolean isPrime = true;
int stoppingPoint = (int) (Math.pow(i, 0.5) + 1);
for (int p : primes) {
if (i % p == 0) {
isPrime = false;
break;
}
if (p > stoppingPoint) { break; }
}
if (isPrime) { primes.add(i); }
}
// System.out.println(primes);
return (ArrayList<Integer>) primes;
//System.out.println(primes.size());
}
public static void count(ArrayList<Integer> num) {
int count = 0;
for (int i = 0; i <= num.size() - 1; i++) {
int number = num.get(i);
String num1 = String.valueOf(number);
int sum = 0;
for (int j = 0; j < num1.length(); j++) {
sum = Integer.parseInt(num1.charAt(j) + "") + sum;
if (sum == 14) { count++; }
}
System.out.println(sum);
}
System.out.println(count);
}
}
You should check whether sum == 14 outside the inner for loop. What happens now is that you also count those primes for which the sum of digits is larger than 14 but the sum of the digits in some prefix of the prime is equal to 14.
This part...
if (sum == 14) {
count++;
}
should be outside the inner for-loop - i.e. you want to do it each time you pass through the i for-loop, but not each time you pass through the j for-loop.
Like this:
public static void count(ArrayList<Integer> num) {
int count = 0;
for (int i = 0; i <= num.size() - 1; i++) {
int number = num.get(i);
String num1 = String.valueOf(number);
int sum = 0;
for (int j = 0; j < num1.length(); j++) {
sum = Integer.parseInt(num1.charAt(j) + "") + sum;
}
System.out.println(sum);
if (sum == 14) {
count++;
}
}
System.out.println(count);
}