I have been assigned the task of writing a program that lists all numbers 1 to 10000 that are the sum of two odd prime numbers squared (ex. 3^2 + 5^2 = 34), then prints the total count of these numbers. However, my program does not recognize that 3^2 + 5^2 is the same thing as 5^2 + 3^2. This causes the program to print duplicates of most of the numbers. Which in turn also affects the total count of the numbers. How can I prevent the program from printing duplicates and adding them to the total count?
import java.util.ArrayList;
/*
* Write a program that lists all numbers 1 to 10000 that are the sum of two
* odd prime numbers squared (ex. 3^2 + 5^2 = 34), then prints the total
* count of these numbers
*/
public class labproblem {
public static void main(String[] args) {
// 100*100 = 10000, the maximum
int maxvalue = 100;
ArrayList<Integer> primes = new ArrayList<Integer>();
// Checks every number until max value is reached
for (int n = 1; n < maxvalue; n++) {
boolean prime = true;
// checks if n is prime
for (int j = 2; j < n; j++) {
if (n % j == 0) {
prime = false;
break; // exits this for loop
}
}
if (prime && n != 1) {
// adds the prime number to the list of prime numbers
primes.add(n);
}
}
// declaring/initializing
double totalcount = 0;
double product = 0;
// sets i2 to the odd prime numbers
for (int i2 : primes) {
// sets i to the odd prime numbers
for (int i : primes) {
// starting at 3 first increases i, then i2
if (i >= 3 && i2 >= 3) {
product = Math.pow(i, 2) + Math.pow(i2, 2);
// Adds 1 to the count after each execution
if (product <= 10000)
totalcount = totalcount + 1;
// Prints the product of the two primes squared
if (product <= 10000)
System.out.println(product);
}
}
}
// Prints the total count of the products
System.out.println(totalcount);
}
}
You could just use a brute force solution, i.e. add your products to a list and don't display them again if already in the list; do something along the lines of:
List<Integer> products = new ArrayList<>();
if (!products.contains(product)) {
products.add(product);
System.out.println(product);
}
Use a Set. Sets do not hold duplicates.
Set<Double> set = new HashSet<>();
for (int i2 : primes) {
for (int i : primes) {
if (i >= 3 && i2 >= 3) {
Double calc = Math.pow(i, 2) + Math.pow(i2, 2);
if(calc <= 10000){
set.add(calc);
}
}
}
}
//No need to count or track anything
// For each Double called 'product' in 'set' send to an anonymous function
set.forEach((product) -> System.out.println(product));
System.out.println("Total Count is " + set.size());
This will print each unique prime calculation you want, and then the total.
without changing much of your code, how about adding couple lines in between your code starting with ** in code snippet below.
**ArrayList<Integer> processed = new ArrayList<>();**
//sets i2 to the odd prime numbers
for (int i2 : primes) {
**processed.add(i2);**
// sets i to the odd prime numbers
for (int i : primes) {
//starting at 3 first increases i, then i2
if (i >= 3 && i2 >= 3 **&& !processed.contains(i)**) {
product = Math.pow(i, 2) + Math.pow(i2, 2);
Related
Highly divisible triangular number, my solution
My solution of challenge from Project Euler takes too much time to execute. Although on lower numbers it works fine. Anyone could look up to my code and give me any advice to improve it?
The content of the task is:
The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:
(1: 1),
(3: 1,3),
(6: 1,2,3,6),
(10: 1,2,5,10),
(15: 1,3,5,15),
(21: 1,3,7,21),
(28: 1,2,4,7,14,28).
We can see that 28 is the first triangle number to have over five divisors.
What is the value of the first triangle number to have over five hundred divisors?
`public static void main(String[] args) {
int sum = 0;
int count = 0;
for (int i = 1; i <= Integer.MAX_VALUE; i++) {
sum += i;
for (int j = 1; j <= sum; j++) {
if (sum % j == 0) {
count++;
}
}
if (count > 500) {
System.out.println(sum);
break;
} else {
count = 0;
}
}
}`
Consider any set of primes (p1, p2, p3. . . pn) that factor a given number. Then the total number of divisors of that number are the products of (e1 + 1, e2 + 1, e3 + 1 ... en+1) where e is the exponent of the corresponding prime factor (i.e. the number of times that prime divides some number N).
There are three pieces to this answer.
The main driver code
the method to find the prime divisors.
and a Primes class that generates successive primes using an iterator.
The Driver
first instantiate the Primes class and initialize the triangleNo
Then continually generate the next triangular number until the returned divisor count meets the requirements.
Primes primes = new Primes();
long triangleNo = 0;
for (long i = 1;; i++) {
triangleNo += i;
int divisors = getDivisorCount(triangleNo, primes);
if (divisors > 500) {
System.out.println("No = " + triangleNo);
System.out.println("Divisors = " + divisors);
System.out.println("Nth Triangle = " + i);
break;
}
}
prints
No = 76576500
Divisors = 576
Nth Triangle = 12375 NOTE: this is the value n in n(n+1)/2.
Finding the prime factors
takes a value to factor and an instance of the Primes class
continues to test each prime for division, counting the number of times the remainder is 0.
a running product totalDivisors is computed.
the loop continues until t is reduced to 1 or the current prime exceeds the square root of the original value.
public static int getDivisorCount(long t, Primes primes) {
primes.reset();
Iterator<Integer> iter = primes;
int totalDivisors = 1;
long sqrtT = (long)Math.sqrt(t);
while (t > 1 && iter.hasNext()) {
int count = 0;
int prime = iter.next();
while (t % prime == 0) {
count++;
t /= prime;
}
totalDivisors *= (count + 1);
if (prime > sqrtT) {
break;
}
}
return totalDivisors;
}
The Primes class
A class to generate primes with a resettable iterator (to preserve computed primes from previous runs the index of an internal list is set to 0.)
an iterator was chosen to avoid generating primes which may not be required to obtain the desired result.
A value to limit the largest prime may be specified or it may run to the default.
Each value is tested by dividing by the previously computed primes.
And either added to the current list or ignored as appropriate.
if more primes are needed, hashNext invoked a generating to increase the number and returns true or false based on the limit.
class Primes implements Iterator<Integer> {
private int lastPrime = 5;
private List<Integer> primes =
new ArrayList<>(List.of(2, 3, 5));
private int index = 0;
private int max = Integer.MAX_VALUE;
public Primes() {
}
public Primes(int max) {
this.max = max;
}
#Override
public boolean hasNext() {
if (index >= primes.size()) {
generate(15); // add some more
}
return primes.get(index) < max;
}
#Override
public Integer next() {
return primes.get(index++);
}
private void generate(int n) {
outer: for (int candidate = lastPrime + 2;;
candidate += 2) {
for (int p : primes) {
if (p < Math.sqrt(candidate)) {
if (candidate % p == 0) {
continue outer;
}
}
}
primes.add(candidate);
lastPrime = candidate;
if (n-- == 0) {
return;
}
}
}
public void reset() {
index = 0;
}
}
Note: It is very likely that this answer can be improved, by employing numerical shortcuts using concepts in the area of number theory or perhaps even basic algebra.
I'm currently doing problem 3 from Project Euler. This the problem I need to solve:
What is the largest prime factor of the number 600851475143 ?
My code compiles as expected when I enter smaller numbers such as 10,000. But when I enter the number from the problem: 600851475143, nothing happens. Here is my code:
import java.util.ArrayList;
class problem3{
public static void main(String args[]){
ArrayList<Long> rr = findFactors(600851475143L);// rr holds an Array of factors.
rr = largestPrime(rr); // rr now holds an Array of factors that are prime.
int sizeOfrr = rr.size();
long largestPrimeFactor = rr.get(sizeOfrr-1);// prints the last(largest) prime factor
System.out.println(largestPrimeFactor);
/*This loops through all of the prime factors found
for(int i = 0; i<rr.size(); i++){
System.out.println(rr.get(i));
}*/
System.exit(0);
}
// This method returns an array of factors of the Long argument passed into parameter number.
public static ArrayList<Long> findFactors(Long number){
ArrayList<Long> factors = new ArrayList<Long>();
for(Long i= 1L; i<=number; i++){ // Divide number by every single digit upto and including itself
// Remember, we need to place L or l after an integer to let the compiler know its a long - not an int primitve.
if(number%i == 0){ // If number modules i is equal to zero, then i is a factor.
factors.add(i); // Append i to the factors array.
}
}
return factors;
}
// Increments the unit divisor, starting at 2L
/* The goal is to find if primeArray[i] has more than one factor. (Exluding 1 itself)
The loop begins at 2L. If primeArray[i]%j == 0, counter will increment by one.
The moment counter hits 2, we know primeArray[i] is not a prime since if it were prime,
the counter would be set to 1 and only 1 (because counter would only increment when j is
equal to primeArray[i] or in otherwords, when it is equal to itself. )
The method below returns an array of all the prime numbers
*/
public static ArrayList<Long> largestPrime(ArrayList<Long> primeArray){
int counter =0;
for(int i = 0; i<primeArray.size(); i++){ // Loops through the prime array
for(Long j = 2L; j<= primeArray.get(i); j++){
// (iL)??; jL++) { // 2L/3 for instance
if(primeArray.get(i)%j == 0){// Is it a factor?
counter++;
}
if(counter > 1){
primeArray.remove(i);
counter = 0;
break;
}
if(j == primeArray.get(i)){
counter = 0;
}
}
}
return primeArray;
}
}
nothing happens
As Qbrute said, you're looping 600851475143 times. It takes really a lot.
Since you have to find the largest prime factor, you don't need to find every factor, so you could skip every even number.
You could find first every prime factor and few others, then keep only the prime ones just comparing the ones you found each other.
Moreover the first loop can end at Math.sqrt(input). What about the (prime) factors above that? Just do input/factor.
Lastly you can keep your array sorted, this way you can stop looking for a prime after the first one. You should also use the primitive every time you can.
These optimization should be enough.
Try this:
public static void main(final String[] args) {
final long n = 600851475143L;
final long largestPrime = findLargestPrimeFactors(n);
System.out.println("The largest prime of " + n + " is: " + largestPrime);
}
public static long findLargestPrimeFactors(final long num) {
final List<Long> factors = new ArrayList<>();
int index = 0;
if ((num % 2L) == 0) {
factors.add(num / 2L);
factors.add(2L);
index = 1;
}
final long end = Double.valueOf(Math.floor(Math.sqrt(num))).longValue();
for (long i = 3L; i <= end; i += 2) { // skip every even number
if ((num % i) == 0) {
// This way the list is sorted in descending order
factors.add(index++, (num / i));
factors.add(index, i);
}
}
final long largestPrime = retainsLargestPrime(factors);
return largestPrime != 1L ? largestPrime : num; // if largestPrime is 1 it means that num is a prime number
}
private static long retainsLargestPrime(final List<Long> factors) {
long largestPrime = 1L;
if ((factors != null) && !factors.isEmpty()) {
final int size = factors.size();
for (int i = 0; (i < size) && (largestPrime == 1L); i++) {
boolean isPrime = true;
final long l = factors.get(i);
for (int j = i + 1; (j < size) && isPrime; j++) {
isPrime = !((l % factors.get(j)) == 0); // stop the inner loop as soon as possible
}
if (isPrime) {
largestPrime = l;
}
}
}
return largestPrime;
}
https://www.codechef.com/problems/PRIME1
If you don't wish to open the link here's a short description of the question below :
This problem asks us to print all prime number within a given range.
There are 10 test cases and each one will provide us a start and end value of a range.
The start and end of this range can take values between 1 and 10^9.
The difference between the start and end values is 10^5 or lesser.
The time limit for the problem is 2 seconds. (that is, for all 10 test cases together)
My thinking on this:
A common estimate is that the online judge used by Codechef can perform ~10^7 operations in 1 second.
We have 10 test cases and in the worst case each one will have a range of 10^5 (since that's the max range given). Now,
10*(10^5)= 10^6 , which is the max number of operations we can perform in 1 second, so for each number in the range we must identify if it is prime in O(1).
Approaches:
1. Simple method for testing primality - Iterate through all numbers from 2 to n-1 and for every number check if it divides n
Ans: Won't work because for the worst case,
= (numbers of the highest size) * (total numbers in max range) * (total test cases)
= (10^9 * 10^5) * 10
= 10^15
2. Square root method to check if prime
Ans: Won't work because, in the worst case,
= (calculating sq. root of numbers of size 10^9) * (total numbers in max range) * (total test cases)
= (~10^4) * (10^5) * 10
= 10^10
3. Using Sieve of Eratosthenes
Precompute primes from 1 to 32000 (this number because it is approx the sq. root of 10^9)
Then to check of a value within the range is primeor not-
if value is between 1 and 32000
directly refer the precomputed value
else
try dividing that value by all precomputed primes, if it divides evenly then its not a prime
Ans: won't work because, in the worst case,
= (number of primes between 1 and 32000) *(total numbers in max range) * (total test cases)
= (3234) * (10^5) * (10)
= 10^9
Code for approach 3:
import java.util.*;
import java.io.*;
class Main
{
static ArrayList<Integer> sieve(ArrayList<Integer> primes)
{
int[] prime=new int[32001];
for(int i=2; i<32001; i++)
{
if(prime[i]==0)
{
for(int j=i+i; j<32001; j+=i)
{
prime[j]=1;
}
}
}
for(int i=2; i<32001; i++)
{
if(prime[i]==0)
{
primes.add(i);
}
}
return primes;
}
public static void main(String[] args)
{
int t,m,n,flag;
ArrayList<Integer> primes= new ArrayList<Integer>();
FastReader scanner= new FastReader();
t=scanner.nextInt();
primes= sieve(primes);
while(t-- > 0)
{
m=scanner.nextInt();
n=scanner.nextInt();
for(int i=m; i<=n; i++)
{
if(i < 32001)
{
if(primes.contains(i))
{
System.out.println(i);
}
}
else
{
flag=0;
for(int j=0; j<primes.size(); j++)
{
if(i%primes.get(j) == 0)
{
flag=1;
break;
}
}
if(flag==0)
{
System.out.println(i);
}
}
}
System.out.println();
}
}
}
While approach 1 obviously didn't work, approach 2 and 3 surprisingly passed!
I'm guessing it passed because the test cases for the problem were weak.
A strong test case would be something like:
10
999900000 1000000000
999899999 999999999
999899998 999999998
999899997 999999997
999899996 999999996
999899995 999999995
999899994 999999994
999899993 999999993
999899992 999999992
999899991 999999991
I ran approach 3 for this test case and it is always taking more than 2 seconds to compute.
If this question did have strong test cases, what would be the correct approach to solve it with the given constraints?
If you going to try figure out prime numbers in a range use the Sieve of Eratosthene algorithm. The basic premise of Sieve is that give a range of numbers you eliminate all numbers that are multiples of prime factors (i.e once we establish that 2 is prime, we eliminate all its multiples ...4, 6, 8, etc)
A implementation of this would be as follows:
private void printPrimes(int max) {
int [] prime = new int[max + 1];
for (int i = 1; i <= max; i++) {
prime[i] = i; // Assume everything is prime initially
}
// if number is prime, then multiples of that factor are not prime
for (int f = 2; f * f <= max; f++) {
if (prime[f] != 0) {
for (int j = f; f * j <= max; j++) {
prime[f * j] = 0;
}
}
}
int counter = 0;
for (int i = 1; i <= max; i++) {
if (prime[i] != 0) counter++;
}
prime = Arrays.stream(prime).filter(i -> i != 0).toArray();
System.out.println("There are " + counter + " primes between 1 and " + max);
System.out.println(Arrays.toString(prime));
}
After a week that I spent stuck on this problem I can't find where is my mistake.
the problem is:
A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.
A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.
As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.
Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.
so my code is:
package eulerProject;
import java.util.*;
import java.math.BigInteger;
public class e23 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
BigInteger sum = BigInteger.ZERO;
for (int i = 1; i <= 28123; i++) {
if (!check(i))
list.add(i);
}
System.out.println(list);
for (int i = 0; i < list.size(); i++)
sum = sum.add(BigInteger.valueOf(list.get(i)));
System.out.println(sum);
}
public static boolean check(long z) {
long y = 0;
for (long i = 1; i <= z / 2; i++) {
if (abundant(i)) {
y = z - i;
if (abundant(y)) {
return true;
}
y = 0;
}
}
return false;
}
public static long sum(long x) {
long sum = 0;
for (int i = 1; i < (Math.sqrt(x)); i++) {
if (x % i == 0) {
if (x / i == i) {
sum += i;
} else {
sum = sum + i + (x / i);
}
}
}
sum = sum - x;
return sum;
}
public static boolean abundant(long x) {
if (sum(x) > x)
return true;
return false;
}
}
I'll just explain the methods:
"sum" - sums all the proper divisors of a number.
(like number = 12 , so it sum: 1+2+3+4+6.)
"abundant" - just checks if the number is abundant or not by compairing the sum of his divisors and the number itself.
"check" - generating two numbers which their sum is the number we checking - and checking if the both numbers are abundant. if they are so returns true.
and the main just generating numbers until the max limit, adding to list and then I sum the list.
my answer is: 4190404.
the correct answer is: 4179871.
where is the mistake?
Your sum method doesn't get the correct sum for perfect squares because your loop stops before the square root. For example, if you called sum(16), the loop would run up to i = 3 and stop, so 4 would not contribute to the sum.
Solution:
(I also fixed some inefficiencies.)
public static long sum(long x){
long sum = 1;
int sqrt = (int)Math.sqrt(x);
for (int i = 2; i <= sqrt; i++) {
if (x % i == 0) {
sum += i + (x/i);
}
}
//checks if perfect square and subtracts out extra square root.
if(sqrt * sqrt == x) sum -= sqrt;
return sum;
}
I have a given number. How can I find the factors of that number (for example, 5 and 3 for the number 15)? Here is the code I tried:
int factor1 = 2;
while ((a % factor1 != 0) && (a >= factor1)) {
d++;
}
if (factor1 == a){
d = 1;
}
But this gives me only the smallest factor (i.e a=3 all the time). I would like to get a random set of factors.
Loop through each number from 1 to N inclusively using the modulus operator (%). If n%currentNumber==0, they are a factor. Below, I did this using a for loop, outputting each factor as it is found.
int number=15;
for(int i = 1; i <= number; i++){
if(number%i==0){
System.out.println("Found factor: " + i);
}
}
As Theo said in a comment on this post, you can also use number/2, and arbitrarily include 1 and number.
int number=2229348;
System.out.println("Found factor: " + 1);
for(int i = 2; i <= number/2; i++){
if(number%i==0){
System.out.println("Found factor: " + i);
}
}
System.out.println("Found factor: " + number);
You can iterate through the numbers from 2 to a/2 and check if the given number divides a, which is done using the % operator:
int a = 15;
System.out.print("Divisors of " + a + ": ");
for(int i = 2; i <= a/2; ++i) {
if(a % i == 0) {
System.out.print(i + " ");
}
}
System.out.println();
This code prints all of the divisors of a. Not that you most probably want to ignore 1, since it divides all integers. Moreover, you don't need to check the numbers until a, because no number bigger than a / 2 can actually divide a apart from a itself.
The while loop with default values of a=15 and multiple=2 is already in an infinite loop. You need to correct that and check for subsequent increments of multiple whenever a%multiple ! = 0
public class Factors {
public static void main(String[] args){
/**
int multiple1=2,d=0,a=15; //multiple to be rephrased as factor
while((a%multiple1 != 0)&&(a>=multiple1)){
multiple1++; //this will increment the factor and check till the number itself
//System.out.println(multiple1+" is not a factor of a");
}
if(multiple1==a){
d=1;
}
*commented the original code
*/
int factor=1,d=0,a=20; //multiple rephrased as factor
while(a/2>=factor){ //re-arranged your while condition
factor++;
if((a%factor==0))
d++; //increment factor count whenever a factor is found
}
System.out.println("Total number of factors of a : "+(d+2)); // 1 and 'a' are by default factors of number 'a'
}
}
To find all factors inlcuding 1 and the number itself you can do something like below:
//Iterate from 2 until n/2 (inclusive) and divide n by each number.
//Return numbers that are factors (i.e. remainder = 0). Add the number itself in the end.
int[] findAllFactors(int number) {
int[] factors = IntStream.range(1, 1 + number / 2).filter(factor -> number % factor == 0).toArray();
int[] allFactors = new int[factors.length+1];
System.arraycopy(factors,0,allFactors,0,factors.length);
allFactors[factors.length] = number;
return allFactors;
}
To find only prime factors you can do something like this:
//Iterate from 2 until n/2 (inclusive) and divide n by each number.
// Return numbers that are factors (i.e. remainder = 0) and are prime
int[] findPrimeFactors(int number) {
return IntStream.range(2, 1 + number/ 2).filter(factor -> number % factor == 0 && isPrime(factor)).toArray();
}
Helper method for primality check:
//Iterate from 2 until n/2 (inclusive) and divide n by each number. Return false if at least one divisor is found
boolean isPrime(int n) {
if (n <= 1) throw new RuntimeException("Invalid input");
return !IntStream.range(2, 1+n/2).filter(x -> ((n % x == 0) && (x != n))).findFirst().isPresent();
}
If you are not on Java 8 and/or not using Lambda expressions, a simple iterative loop can be as below:
//Find all factors of a number
public Set<Integer> findFactors(int number) {
Set<Integer> factors = new TreeSet<>();
int i = 1;
factors.add(i);
while (i++ < 1 + number / 2) {
if ((number % i) == 0) {
factors.add(i);
}
}
factors.add(number);
return factors;
}
public class Abc{
public static void main(String...args){
if(args.length<2){
System.out.println("Usage : java Abc 22 3");
System.exit(1);
}
int no1=Integer.parseInt(args[0]);
int no=Integer.parseInt(args[1]),temp=0,i;
for(i=no;i<=no1;i+=no){
temp++;
}
System.out.println("Multiple of "+no+" to get "+no1+" is :--> "+temp);
//System.out.println(i+"--"+no1+"---"+no);
System.out.println("Reminder is "+(no1-i+no));
}
}