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;
}
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 have a program that computes amicable pairs of numbers up to a certain limit and prints them out to Stdout. FYI - two numbers are amicable if each is equal to the sum of the proper divisors of the other (for example, 220 and 284).
My program works fine for the first 8 or so pairs, but the problem is when the limit gets to a very high number e.g 5 million it becomes very slow. Is there a way to optimize this so that it computes much faster?
Here is my code
public class Amicable{
private static int num1, num2, limit = 5000000;
public static void main(String[] args){
for(int i = 1; i < limit;i++){
num1= sumOfDivisors(i);
num2 = sumOfDivisors(i)
if(num1 == num2){
System.out.println(num2 + " " + num1);
}
}
}
}
private static int sumOfDivisors(int n){
int sum = 0;
for(int i=1;i<=n/2;i++){
if(n%i==0){
sum =sum+i;
}
}
return sum;
}
}
You should make the innermost loop efficient.
static int sumOfDivisors(int n) {
int sum = 1;
int max = (int) Math.sqrt(n);
if (n > 1 && max * max == n) // in case of n is perfect square number
sum -= max;
for (int i = 2; i <= max; ++i)
if (n % i == 0)
sum += i + n / i;
return sum;
}
If n = 220, it is divisible by 2, so you can add 2 and 110 to the sum at the same time. However, if n is a perfect square number, for example n = 100, it is divisible by 10, but if 10 and 10 are added, they will duplicate, so subtract it in advance.
output for limit =2000000:
220 284
1184 1210
2620 2924
5020 5564
6232 6368
10744 10856
12285 14595
17296 18416
63020 76084
66928 66992
.....
1468324 1749212
1511930 1598470
1669910 2062570
1798875 1870245
It took 7 seconds on my PC.
You could change the statement of "if(i<num1)" to "if(i<num1 || num1<limit)".
This is a more efficient and faster approach.
Inside sumOfDivisors:
Start iteration from 2. (no a big deal) and add 1 during return time with sum as 1 is also a divisor.
Modify loop termination logic, i <= Math.sqrt(n).
For any number ‘num’ all its divisors are always less than and equal to ‘num/2’ and all prime factors are always less than and equal to sqrt(num).
If n%i == 0, then check, both divisors are are equal or not. If equal, take one if not equal then take both one.
private static int sumOfDivisors(int n) {
int sum = 0;
int sqrt = Math.sqrt(n);
for (int i = 2; i <= sqrt; i++) {
if (n % i == 0) {
if(i == (n/i))
sum = sum + i;
else
sum += (i+ n/i);
}
}
return sum+1;
}
This is my code for the Codewars problem (Java) yet I cannot make it work. I'm pretty sure I've made a stupid mistake somewhere because of my lack of experience (coding for 4 months)
public static int zeros(int n) {
int f = 1;
int zerocount = 0;
for(int i = 2 ; i <= n; i++){
f *= i;
}
String factorial = String.valueOf(f);
String split [] = factorial.split("");
for(int i = 0; i < split.length; i++){
String m = split[i];
if(m.equals( "0")){
zerocount ++;
}
else {
zerocount = 0;
}
}
return zerocount;
}
}
In fact, you do not need to calculate the factorial because it will rapidly explode into a huge number that will overflow even a long. What you want to do is count the number of fives and twos by which each number between 2 and n can be divided.
static int powersoffive(int n) {
int p=0;
while (n % 5 == 0) {
p++;
n /= 5;
}
return p;
}
static int countzeros(int n) {
int fives = 0;
for (int i = 1; i <= n; i++)
fives += powersoffive(i);
return fives;
}
Note: Lajos Arpad's solution is superior.
As pointed out by other users your solution will probably not be accepted because of the exploding factorial you are calculating.
About the code you wrote there are two mistakes you have made:
You are calculating the factorial in the wrong way. You should start with i = 2 in the loop
for(int i = 2; i <= n; i++){
f *= i;
}
Also in Java you cannot compare strings using ==. This is not valid
if(m == "0")
You should compare them like this
if(m.equals("0"))
Anyway this is how I would have resolved the problem
public static int zeros(int n) {
int zerocount = 0;
for (int i = 5; n / i > 0; i *= 5) {
zerocount += n / i;
}
return zerocount;
}
A zero in a base-10 representation of a number is a 2*5. In order to determine the number of trailing zeroes you will need to determine how many times can you divide your number with ten, or, in other words, the minimum of the sum of 2 and 5 factors. Due to the fact that 5 is bigger than 2 and we go sequentially, the number of fives will be the number of trailing zeroes.
A naive approach would be to round down n/5, but that will only give you the number of items divisible with 5. However, for example, 25 is divisible by 5 twice. The same can be said about 50. 125 can be divided by 5 three times, no less.
So, the algorithm would look like this:
int items = 0;
int power = 5;
while (power < n) {
items += (int) (n / power);
power *= 5;
}
Here small numbers are in use in relative terms, but it's only a proof of concept.
You do need to use brute force here and you integers will overflow anyway.
With multiplication trailing zero appears only as the result of 2*5.
Now imagine the factorial represented by a product of it's prime factors.
Notice that for every 5 (five) we will always have 2 (two).
So to calculate the number of zeroes we need to calculate the number of fives.
That can be implemented by continuously dividing N by five and totaling results
In Java code that will be something like this:
static int calculate(int n)
{
int result = 0;
while (n > 0 ) {
n /= 5;
result += n;
}
return result;
}
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);
Can any body help to understand this java program?
It just prints prime numbers, as you enter how many you want and it works well.
class PrimeNumbers
{
public static void main(String args[])
{
int n, status = 1, num = 3;
Scanner in = new Scanner(System.in);
System.out.println("Enter the number of prime numbers you want");
n = in.nextInt();
if (n >= 1)
{
System.out.println("First "+n+" prime numbers are :-");
System.out.println(2);
}
for ( int count = 2 ; count <=n ; )
{
for ( int j = 2 ; j <= Math.sqrt(num) ; j++ )
{
if ( num%j == 0 )
{
status = 0;
break;
}
}
if ( status != 0 )
{
System.out.println(num);
count++;
}
status = 1;
num++;
}
}
}
I don't understand this for loop condition
for ( int j = 2 ; j <= Math.sqrt(num) ; j++ )
why we are taking sqrt of num...which is 3....why we assumed it as 3?
Imagine that n can be divided by a number k that is greater than sqrt(n). Then you have:
n = k * j
where j is a number which must be less than sqrt(n) (if both k and j are greater than sqrt(n) then their product would be greater than n).
So you only need to find the divisors that are less than or equals to sqrt(n) and you can find those that are greater than or equals to sqrt(n) by a simple division. In my example, once you have found j, you can find k = n / j.
The line in question is basically trying to find numbers that are factors of your given number (and eliminating them as not-primes). If you find no factors of a given number then you can say that the number is prime.
As far as finding factors goes, you only need to go up to sqrt(N) because if you go any higher you are looking at numbers you have already seen before. This is because every time you find a factor you actually find two factors. If a is a factor of N then N/a and a are both factors of N.
A number N is prime if the only integers that satisfy N = A*B are 1 and N (or N and 1).
Now to check a number N as prime we could search all A from 2 to N and B from 2 to N, to see if N=A*B. That would take O(N^2) time, and is really inefficient.
It turns out that we only need to divide N by a number and see if there is a remainder. This brings it down to O(N).
And further, we don't need to check all the way from A=2 to A=N. If A is greater than sqrt(N), then B must be less than sqrt(N). Therefore we only need to check A from 2 to sqrt(N) to see if N/A has a remainder.
If I'm right there is a theory in math, saying that nearly all prime numbers can be determined when checking numbers from 2 to square root of n instead of checking all numbers from 2 to n oder 2 to n/2.
The factor of a number can lie only from 1 to sqrt of num. So instead of checking from 1 till num for its factors, we check for all numbers from 1 to sqrt(num) so see if any of them divides num. If any divides num, it is not prime, else it is. This improves efficiency of code.
A quick but dirty solution..
import java.util.Scanner;
class testing
{
public static void main(String args[])
{
Scanner input = new Scanner(System.in);
int n, i, j, count = 1;
System.out.print("How many Numbers ? : ");
n = input.nextInt();
for(j = 1;count<=n;j++)
{
if(j==1 || j==2)
{
System.out.println(j);
count++;
continue;
}
for(i=2;i<=j/2;i++)
{
if(j%i==0)
break;
else if(i == j/2 && j%i != 0)
{
System.out.println(j);
count++;
}
}
}
}
}
public class PrimeNumber {
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList a = new ArrayList();
for (int i = 1; i <= 100; ++i) {
if (isPrime(i))
a.add(i);
}
System.out.println("List : " + a);
}
public static boolean isPrime(int value) {
if (value <= 1)
return false;
if ((value % 2) == 0)
return (value == 2);
for (int i = 3; i <= value - 1; i++) {
if (value % i == 0) {
return false;
}
}
return true;
}
}