I have got a solution for problem 21 in python and it gives the right answer. I tried out someone else's java code and I get the same answer for a value of 10000 and 100000 but when 1000000 is tried, the solution returned by my code differs from two other solutions returned by java code even though all three solutions returned are same for tested values of 10000 and 1000000 and 50000. Anyone got any ideas?
My Python code
def amicable_pairs(n):
"""returns sum of all amicable pairs under n. See project euler for
definition of an amicable pair"""
div_sum = [0]*n
amicable_pairs_set = [0]*n
for i in range(1, n):
for j in range(i*2, n, i):
div_sum[j] += i
#for i in range(1, n):
# div_sum[i] = sum([j + i/j for j in range(2, int(math.sqrt(i)) + 1) if i % j == 0 and i != i/j])
# div_sum[i] = div_sum[i] + 1
#print div_sum
for j in range(n):
if div_sum[j] < n and div_sum[div_sum[j]] == j and div_sum[j] != j:
amicable_pairs_set[j] = j
amicable_pairs_set[div_sum[j]] = div_sum[j]
return sum(amicable_pairs_set)
Java code 1:
public class AmicableNumbers {
public static void main(String[] args) {
long strTime = System.currentTimeMillis();
int sum_ami = 0;
for (int j = 1; j < 1000000; j++) {
int ad = sum_devisors(j);
if (((sum_devisors(ad)) == j) && (j != ad)) {
sum_ami += j;
}
}
System.out.println(sum_ami);
long endTime = System.currentTimeMillis();
System.out.println("time is " + (endTime - strTime) + " ms");
}
public static int sum_devisors(int number) {
if ((number == 1) || (number == 2)) {
return 1;
}
int sum = 0;
int k = (int) Math.sqrt(number);
for (int i = 2; i < k; i++) {
if (number % i == 0) {
sum += i;
sum += (number / i);
}
}
if (k * k == number) {
sum += k;
}
return (sum + 1);// every number divided by 1
}
}
Java code 2:
import java.util.Scanner;
public class AmicableNumbers {
/**
* #author Pavan Koppolu
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//scan the input
System.out.println("Enter a number, to find out sum of amicable numbers: ");
Scanner scan=new Scanner(System.in);
int input=scan.nextInt();
long before=System.currentTimeMillis();
// getting the result
long result=sumOfAllAmicableNumbersUptoGivenNumber(input);
long after=System.currentTimeMillis();
// prints the result on the console
System.out.println("Sum of all amicable numbers below "+input+" : "+result+" Elasped Time : "+(after-before)+" ms");
}
/*
* calculate the sum of the amicable numbers upto the given number
*/
private static long sumOfAllAmicableNumbersUptoGivenNumber(int input)
{
long sum=0,factorsSum=0,sumOfFactors=0;
for(long j=2;j<input;j++)
{
factorsSum=getFactorsSum(j);
if(j!=factorsSum)
{
sumOfFactors=getFactorsSum(factorsSum);
if(j==sumOfFactors)
sum+=j;
}
else
continue;
}
return sum;
}
/*
* find out the sum of the factors
*/
private static long getFactorsSum(long j)
{
long sum=1;
for(int k=2;k<=Math.sqrt(j);k++)
{
if(j%k==0)
sum+=k+j/k;
}
return sum;
}
}
In fact the solutions returned by all three above differ from each other for an input of 1000000
The point is that there are amicable pairs where one partner is less than 1 million and the other is larger than 1 million, namely
(947835,1125765), (998104,1043096)
The Python code doesn't count them,
for j in range(n):
if div_sum[j] < n and div_sum[div_sum[j]] == j and div_sum[j] != j:
but the Java code counts the smaller members of these pairs. That explains the output of the second Java code, since
25275024 + 947835 + 998104 == 27220963
The output of the first Java code is smaller because it omits the amicable pair
(356408, 399592)
The reason is that
356408 = 596*598
but in the code there is
int k = (int) Math.sqrt(number);
for (int i = 2; i < k; i++) {
thus the divisor sum is miscalculated for all numbers divisible by floor(sqrt(n)) that are not squares (Note that the second Java code miscalculates the divisor sum for all squares).
Related
public class StairCase {
public static int Solution(int n) {
int sum, count = 0;
//Funtion to calculate stair case and use factorial because a solution can have many ways.
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= n; j++) {
for (int k = 0; k <= n; k++) {
sum = i + (j * 2) + (k * 3);
if (sum == n) {
count = count + (fact.fact1(i + j + k) / (fact.fact1(i) * fact.fact1(j) * fact.fact1(k)));
}
}
}
/*logic behind this funtion is that like we have to find no of arrangement abbbccde can we written so we write (8!/(3!*2!))
so after getting like ijk= 1,2,3 I rearranged them in that man ways
(i+j+k)!/i!*j!k! !=factorial/
}
return count;
}
public static void doTestPass() {
boolean result = true;
result = result && (Solution(3) == 4);
result = result && (Solution(4) == 7);
result = result && (Solution(11) == 504);
result = result && (Solution(12) == 927);
result = result && (Solution(13) == 1705);
//working fine till 13 not after that
System.out.println(Solution(14));
System.out.println(Solution(20));
System.out.println(Solution(21));
//14--3127 20--68603 21--94351(orignal ans-- 3136,121415,223317)
if (result) {
System.out.println("All Test Cases Passed");
} else {
System.out.println("Test Case Failed");
}
}
public static void main(String[] Args) {
doTestPass();
}
public class fact
{
static int fact1(int n)
{
//this funtion is to create factorial
int res = 1;
for (int i = 2; i <= n; i++)
{
res = res * i;
}
return res;
}
}
}
The problem has to do with using primitive integers for your factorial method and overflowing the integer limit of 2,147,483,647.
Take a look at trial runs of your factorial code below:
fact1(12) outputs 479001600 which is correct for 12!
fact1(13) outputs 1932053504 which is not 13! which should be 6227020800
This means when you execute fact.fact1(i) in your code, it will be outputting the wrong answer for any value greater than 12. This would require you to rework the data structure you use to hold these big numbers to BigInteger.
The reworked fact method would look like this:
BigInteger fact1(int n) {
// this funtion is to create factorial
BigInteger res = BigInteger.ONE;
for (int i = 2; i <= n; i++) {
res = res.multiply(BigInteger.valueOf(i));
}
return res;
}
With the output of fact1(13) being the correct value of 6227020800 now.
You will need to rework the other aspects of your code now with BigInteger, but you should understand now what your issue was.
I need to write up factorial up to 23! I can do factorial up to 20! but after that I am lost because the number gets too big. I cannot use BigInteger.
I have to store the 0s from the rightmost digit so example outputs:
10! = 3628800 --> fac=36288, num10 = 2
23! = 2585..976640000 --> fac= 2585..97664, num10 = 4
import java.util.Scanner;
public class Factorial10{
public static void main(String[] args){
long fac; // long: factorial is very large
long pre_fac; // to check overflow
int i, n;
int num10;
Scanner sc = new Scanner(System.in);
System.out.print("n? ");
n = sc.nextInt();
// Start from fac = 0! = 1
for(i= 1, fac= 1L; i<n; i++){
pre_fac = fac;
fac *= i;
// check if overflowed
if(pre_fac != fac /i){
System.out.println("Overflowed at " + i + "! = " + fac);
fac = pre_fac; // roll back to the previous, unoverflowed
break;
}
}
System.out.println((i-1) + "! = " + fac + "(fac = , num10 = )");
}
}
```
Most miss a crucial part of your question:
I have to store the 0s from the rightmost digit
10 has the factors 2 and 5, so you only need to store how often each number between 1 and 23 can be divided by 2 and 5.
For example, with 10:
i 1 2 3 4 5 6 7 8 9 10 SUM
div2 0 1 0 2 0 1 0 3 0 1 8
div5 0 0 0 0 1 0 0 0 0 1 2
As we can see, the minimum of both sums is 2, so 10! should end with 00.
Indeed, 10! is 3628800.
The math behind this is 10! = x * 2^8 * 5^2, for some x that can't be divided by 2 or 5.
An other observation is that the number of 5s increases much slower, so we can skip counting the 2s.
With this knowledge, we can calculate the number of ending 0s by checking how often each number divides 5:
private static int numZerosInFactorial(int n) {
int divBy5 = 0;
for (int i = 1; i <= n; i++) {
for (int j = i; (j % 5) == 0; j /= 5) {
divBy5++;
}
}
return divBy5;
}
(There are are a few small improvements you can do to the above method)
The other question now is: Do you really need the value of n!?
And if yes, with what precision? Is it fine to calculate n! with double now?
Thanks to a comment from Michael, I noticed that we can in fact calculate the factorial without the zeros and then use string concatenation to display the result.
When calculating the factorial without zeroes, we have to basically do the opposite of what we did in numZerosInFactorial, so instead of multiplying with a multiple of 5, we divide by 2:
private static long factorialWithoutZeroes(int n) {
long result = 1;
for (int i = 1; i <= n; i++) {
long div = 1;
int j;
for (j = i; (j % 5) == 0; j /= 5) {
div *= 2;
}
result = result / div * j;
}
return result;
}
The final result would be:
// We have already read n from stdin
long fac = factorialWithoutZeroes(n);
int num10 = numZerosInFactorial(n);
System.out.println(n + "! = " + (fac + "0".repeat(num10)) + " (fac = " + fac + " , num10 = " + num10 + ")");
Indeed, this approach works up to n == 23. And the output format is a good hint that this is the expected approach.
Have you try to use double instead of long. As documentation in Double.Max - it can hold up to 1.7976931348623157e+308
Just implement your own kind of big integer:
import java.util.Arrays;
class Main {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
int[] factorial = factorial(n);
for (int i = factorial.length - 1; i >= 0; i--) {
System.out.print(factorial[i]);
}
}
static int[] factorial(int n) {
int[] factorial = { 1 };
for (int i = 1; i <= n; i++) {
factorial = multiply(factorial, i);
}
return factorial;
}
static int[] multiply(int[] multiplicand, int multiplicator) {
int carry = 0;
for (int j = 0; j < multiplicand.length; j++) {
multiplicand[j] = multiplicand[j] * multiplicator + carry;
carry = multiplicand[j] / 10;
multiplicand[j] %= 10;
}
while (carry > 0) {
multiplicand= Arrays.copyOf(multiplicand, multiplicand.length + 1);
multiplicand[multiplicand.length - 1] = carry % 10;
carry /= 10;
}
return multiplicand;
}
}
Try it online!
If you can't use BigInteger, then you could try implementing your own big number library:
How to handle very large numbers in Java without using java.math.BigInteger
You can use the class BigDecimal of java.lang.math
But that can take all your memory.
Is there any replacement of long double in 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.
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.
I am trying to get the first primitive root of a prime number:
private static int GetPrime(int factors[], int modul) {
for (int i = 2; i < modul; i++) {
int j = 0;
while (j < factors.length) {
int power = (modul - 1) / factors[j];
long g = (long) Math.pow(i, power);
long mod = g % modul;
if (mod == 1) {
j++;
break;
} else if (j + 1 == factors.length) {
return i;
}
j++;
}
}
return 0;
}
As parameters i have prime factors of number (factors) and prime number (modul). I tried to implement function for finding the first prime root, for some numbers it works, but for other it fails. Forexample it gives the correct answer for 23 which is 5, but for 71 it fails, instead of 7 it gives 3. I can't figure out what is wrong.
Basically formula is n^((modul-1)/factor) % modul, if for one of factors the reminder for each n is 1, then n is not a prime root.