The goal of the code is to generate a sequence that operates as follows:
The first number is given, 2. To find the next number in the sequence: multiply all numbers in the sequence together than add 1. The smallest prime divisor of that number is the next number in the sequence. The first three number are [2, 3, 7]. So 237 + 1 = 43. The smallest prime factor is 43. So 43 is the next number. However when my code reaches the 5th number in the sequence it generates 139, instead of 13. 237*43 + 1 = 1807. 1807/13 = 139. So 13 should be next.
Problem: When my code reaches the 5th number in the sequence it generates 139
Note: Using BigInteger because reaching the 8th, 9th,... do not work with Int
import java.math.BigInteger;
import java.util.Scanner;
import java.util.ArrayList;
public class LPMSeq {
public static BigInteger spd(BigInteger y) {
ArrayList<BigInteger> primes = new ArrayList<BigInteger>();
int retval = 0;
int Nth_prime = 25200;
BigInteger TWO = new BigInteger("2");
BigInteger bi = new BigInteger("1");
primes.add(TWO);
int i = 1;
//generates N prime numbers using isProbablePrime
while (i < Nth_prime) {
bi = bi.add(TWO);
if (bi.isProbablePrime(80)) {
i++;
primes.add(bi);
}
}
BigInteger zero = new BigInteger("0");
// finds smallest prime divisor
for (int n = 0; n < Nth_prime; n++) {
BigInteger modded = y.mod(primes.get(n));
if (modded.equals(zero)) {
retval = primes.get(n).intValue();
}
}
return BigInteger.valueOf(retval);
}
public static ArrayList<BigInteger> LpmSeq(int k) {
//ArrayList holding the sequence
ArrayList<BigInteger> Seq = new ArrayList<BigInteger>();
BigInteger two = new BigInteger ("2");
//Add two to sequence (first number in sequence)
Seq.add(two);
while (Seq.size() < k) {
BigInteger x = new BigInteger ("1");
for (int i = 0; i < Seq.size(); i++) {
x = x.multiply(Seq.get(i));
}
BigInteger y = x.add(BigInteger.ONE);
BigInteger spd = spd(y);
Seq.add(spd);
}
return Seq;
}
public static void main(String[] args) {
//Create Scanner
Scanner userinput = new Scanner(System.in);
// Variables
int k = 0;
//Prompt user and get input
System.out.println("How many elements would you like in the sequence? (Please enter an integer)");
k = userinput.nextInt();
System.out.println(LpmSeq(k));
}
}
Your loop that finds the smallest prime factor doesn't work if y isn't prime:
// finds smallest prime divisor
for (int n = 0; n < Nth_prime; n++) {
BigInteger modded = y.mod(primes.get(n));
if (modded.equals(zero)) {
retval = primes.get(n).intValue();
}
}
It finds the largest prime factor, because it doesn't stop when it finds the first prime factor. Because the factorization of 1807 is 13 x 139, it skips 13 and returns 139.
Place a break after you assign retval:
for (int n = 0; n < Nth_prime; n++) {
BigInteger modded = y.mod(primes.get(n));
if (modded.equals(zero)) {
retval = primes.get(n).intValue();
break;
}
}
Also, I find it curious that you're checking all primes through the 25,200th (and re-calculating all 25,200 of them each call). You only need to check primes through the square root of y.
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 would like to generate a ten digit account number greater than 1,000,000,000 and less than 9,999,999,999. I have 3 separate attempts that all are almost operational, but after 9 digits I either receive an error or a number that is generated is not an expected outcome.
for(int i = 0; i < 10; i++) {
int r = rand.nextInt(10);
int l = (int)Math.pow(10,i);
int currentRand = r * l;
System.out.println("i: "+ i+ ", random int: "+ r+", ten to the pow i: "+ l+ ", currentRand: "+ currentRand);
}
int n = rand.nextInt(89999) + 10000;
int n1 = rand.nextInt(89999) + 10000;
int n2 = Math.multiplyExact(n*100000);
System.out.println(n);
System.out.println(n1);
System.out.println(n2);
int accountNum;
String ofNumber = "";
for(int i = 0; i < 10;i++) {
ofNumber += String.valueOf(rand.nextInt(10));
System.out.println(ofNumber);
}
accountNum = Integer.parseInt(ofNumber);
The largest value representable as an int is 2147483647, so about 78% of the 10-digit number range is larger than what can be stored in an int. Use either long or BigInteger.
As Jim Garrison says, your account numbers won't fit into an int but they will fit into a long.
The Random class allows you to generate a stream of random long numbers between a minimum (inclusive) and a maximum (exclusive). Here is an example of this that prints out 10 account numbers:
I have assumed that the smallest account number you want is 1000000000 and the largest 9999999999
import java.util.Random;
public class AccountNumberDemo {
public static void main(String[] args) {
Random rand = new Random();
rand.longs(10, 1_000_000_001L, 10_000_000_000L)
.forEach(System.out::println);
}
}
If you just want one account number in a variable, then this shows how to do it:
import java.util.Random;
public class AccountNumberDemo {
public static void main(String[] args) {
Random rand = new Random();
long accountNumber = rand
.longs(1, 1_000_000_001L, 10_000_000_000L)
.findFirst()
.getAsLong();
System.out.println(accountNumber);
}
}
I am trying to calculate the square root of all the integers below 100 with A precision of up to 10000 digits. I already tried it using Newton's method with Big Decimal, where it eats a lot of time.
So now am using Jarvis method for finding the square root using BigInteger.(I think this method involves less number of calculations and gets rid of the maintenance of decimal digits). Even then my code takes a lot of time.The following piece of code depicts the calculations.
public class SquareRootHackerRankJarvis {
static BigInteger limit;
static BigInteger a;
static BigInteger b;
private static BigInteger squareroot(int n, int digits, BigInteger ten,
BigInteger hundred, BigInteger five) {
limit = ten.pow(digits + 1);
a = BigInteger.valueOf(n * 5);
b = BigInteger.valueOf(5);
while (b.compareTo(limit) == -1) {
if (a.compareTo(b) != -1) {
a = a.subtract(b);
b = b.add(ten);
} else {
a = a.multiply(hundred);
b = (b.divide(ten)).multiply(hundred).add(five);
}
}
return b.divide(hundred);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int P = scanner.nextInt();
int sum = 0;
int p = 1;
BigInteger ten = BigInteger.valueOf(10);
BigInteger hundred = BigInteger.valueOf(100);
BigInteger five = BigInteger.valueOf(5);
for (int i = 1; i <= N; i++) {
if (p * p == i) {
p++;
continue;
}
BigInteger x = squareroot(i, P, ten, hundred, five);
char[] digits = x.toString().toCharArray();
for (int j = 0; j <= P - 1; j++) {
sum += Character.getNumericValue(digits[j]);
}
}
System.out.println(sum);
scanner.close();
}}
Can anyone provided or suggestions about the proper usage of BigInteger for optimum performance?
Comments on improvement of the above algorithm are also welcomed.
BigInteger ten = BigInteger.valueOf(10);
BigInteger hundred = BigInteger.valueOf(100);
BigInteger five = BigInteger.valueOf(5);
Should be moved outside of the function squareroot so they are not created and initialized every time function is called. Make sure they are still accessible in this function.
BigInteger num;
BigInteger limit;
BigInteger a;
BigInteger b;
Should be created outside of the function and should be only initialized on every fucntion call.
Also following line
b = (b.divide(ten)).multiply(hundred).add(five);
can be optimized to
b = b.multiply(ten).add(five);
One observation beyond fast computation of numerous digits of roots of non-squares is that there are just 25 non-compound numbers from 2 to 100.
Next, in addition to introducing constants like Maciej suggested, reduce the "introduction of 0 before the trailing 5" to two operations:
static final BigInteger
ten = BigInteger.TEN,
oneHundred = BigInteger.valueOf(100),
five = BigInteger.valueOf( 5),
fourtyFive = BigInteger.valueOf( 45);
/** Computes <code>digits</code> decimal digits of <code>n</code>
* <em>ignoring</em> (decimal) scaling. */
private static BigInteger sqrtDigitsJarvis(int n, int digits) {
BigInteger
limit = ten.pow(digits + 1), // might be an instance data member
a = BigInteger.valueOf(n*5L), // la*100),
b = five; // BigInteger.valueOf(ib*10 - 45);
// flawed for limit < sqrt(5n)
while (b.compareTo(limit) < 0) {
if (0 <= a.compareTo(b)) { // each branch can be parallelised
a = a.subtract(b);
b = b.add(ten);
} else {
a = a.multiply(oneHundred);
b = b.multiply(ten).subtract(fourtyFive);
}
}
return b.divide(oneHundred);
}
This is a homework problem
How would I reverse an integer in Java with a for loop? The user will input the integer (I don't know how long it will be) and I need to reverse it. ie: If they enter 12345, my program returns 54321.
Here's the catch, you can't use String, StringBuffer, arrays, or other advanced structures in this problem.
I have a basic idea of what I need to do. My problem is...in the for loop, wouldn't the condition need to be x < the length of the integer (number of digits)? How would I do that without String?
Thanks for any input, and I'll add more information if requested.
EDIT:
Of course, after introspection, I realized I should use another for loop to do this. What I did was create a for loop that will count the digits by dividing by 10:
int input = scan.nextInt();
int n = input;
int a = 0;
for (int x = 0; n > 0; x++){
n = n/10;
a = a + 1;
}
EDIT 2:
This is what I have
int input = scan.nextInt();
int n = input;
int a = 0;
int r = 0;
for (int x = 0; n > 0; x++){
n = n/10;
a = a + 1;
}
for (int y = 0; y < n; y++) {
r = r + input%10;
input = input/10;
}
System.out.println(input);
When I run it, it isn't reversing it, it's only giving me back the numbers. ie: if I put in 1234, it returns 1234. This doesn't make any sense to me, because I'm adding the last digit to of the input to r, so why wouldn't it be 4321?
While your original number is nonzero, take your result, multiply it by 10, and add the remainder from dividing the original by 10.
For example, say your original number is 12345. Start with a result of 0.
Multiply result by 10 and add 5, giving you 5. (original is now 1234.)
Multiply result by 10 and add 4, giving you 54. (original is now 123.)
Multiply result by 10 and add 3, giving you 543. (original = 12.)
Multiply result blah blah 5432. (original = 1.)
Multiply, add, bam. 54321. And 1 / 10, in int math, is zero. We're done.
Your mission, should you choose to accept it, is to implement this in Java. :) (Hint: division and remainder are separate operations in Java. % is the remainder operator, and / is the division operator. Take the remainder separately, then divide the original by 10.)
You will need to use math to access each of the digits. Here's a few hints to get your started:
Use the % mod operator to extract the last digit of the number.
Use the / division operator to remove the last digit of the number.
Stop your loop when you have no more digits in the number.
This might not be the proper way but
public static int reverseMe(int i){
int output;
String ri = i + "";
char[] inputArray = ri.toCharArray();
char[] outputArray = new char[inputArray.length];
for(int m=0;m<inputArray.length;m++){
outputArray[inputArray.length-m-1]=inputArray[m];
}
String result = new String(outputArray);
output = Integer.parseInt(result);
return output;
}
public static void reverse2(int n){
int a;
for(int i = 0; i < n ; i ++){
a = n % 10;
System.out.print(a);
n = n / 10;
if( n < 10){
System.out.print(n);
n = 0;
}
}
}
here is the Answer With Correction of Your Code.
import static java.lang.Math.pow;
import java.util.*;
public class MyClass {
public static void main(String args[]) {
Scanner scan=new Scanner(System.in);
int input = scan.nextInt();
int n = input;
int a = 0;
int r = 0;
for (; n > 0;){
n = n/10;
a = a + 1;
}
for (int y = 0; y < input;a--) {
r =(int)( r + input%10*pow(10,a-1));
input = input/10;
}
System.out.println(r);
}
}
This is a problem from CodeSprint3
https://cs3.interviewstreet.com/challenges/dashboard/#problem/50877a587c389
Basically the problem is to calculate the number of possible combinations,nCr for given n and r.Also, 1 <= n <= 1000000000 and 0 <= r <= n.
Output all answers modulo 142857.
Since 6C4=6!/4! 2!
=6*5/2!
=6*5/2*1
I thought overflow could be avoided using division at every step.That is
to start with value of n (n is 6 in this case).
Decrement n and multiply it with previous value (so this becomes 6*5)
Perform division with denominator and then decrement it ( 6*5 /2 and denominator 2 becomes 1)
Repeat the steps until n is less than the of maximum of 2 denominators and in same number of iterations the divisor (Minimum of denominators will become 1)
int count(int n,int r)
{int maxDen=r>(n-r)?r:n-r; //larger number in the denominator
int minDen=n-maxDen; //the smaller number in denominator
double num=1;
for(int j=n;j>maxDen;j--)
{num=j*num; //for C(6,4) example num=6*5 and so on
// System.out.println("num "+num +" minDen "+minDen);
num=num/minDen; //divide num 6*5 in this case by 2
minDen--;
}
num=num%142875; //output the result modulo 142875
return (int) num;
}
But perhaps due to loss precision as more divisions are performed,it gives wrong values but then it still gives correct output for some values.As it stands correct for 22 17 but not for 24 17.
(22 17) = 26334 //gives Correct value
(24 17)= 60353 //wrong value correct value is 60390
(25,17)=81450 //wrong value correct value is 81576
(16 15)= 16 //gives correct value
(87 28)= 54384 //wrong value correct value is 141525
I tried to use num as a BigDecimal and as a consequence i had to replace everything with a BigDecimal to perform the operations.The output then was the same for the inputs which gave correct results in above code.But for inputs which gave wrong results,the program throws an exception
Exception in thread "main" **java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.**
at java.math.BigDecimal.divide(Unknown Source)
at Combination.NcRcount2.count(NcRcount2.java:16)
at Combination.NcRcount2.main(NcRcount2.java:37)
Line 16 is num=num.divide(minDen); //in replacement to earlier used num/minDen,both num and minDen are BigDecimal in this case
Even though if the number does not have an exact decimal representation,given the arbitrary precision of BigDecimal the error in results would have been minimized if it didn't threw an exception.
** If the result of division on floats or doubles does not have an exact decimal representation then why isn't an exception thrown?**
I verified the results using BigDecimal with the dynamic programming approach as
C(n,r)=C(n-1,r-1)+C(n-1,r)
This works correctly in all cases as it appears to me but there must be a better way
BigDecimal Comb (int n, int k)
{ if(k>n-k)
k=n-k;
BigDecimal B[][]=new BigDecimal[n+1] [k+1];
for (int i = 0; i <= n; i++)
{ int min;
if(i>=k)
min=k;
else
min=i;
for (int j = 0; j <= min; j++)
{ if (j == 0 || j == i)
B[i][j] =new BigDecimal(1);
else{
if(j>i-j)
B[i][j]=B[i][i-j];
else
B[i][j] = B[i - 1][j - 1].add(B[i - 1] [j]);
}
}
}
BigDecimal div=new BigDecimal(142857);
return B[n][k].remainder(div);
}
Please suggest me a better way to do this without using BigDecimal
public class Solution {
public static void main(String arg[]) {
Scanner s = new Scanner(System.in);
List<BigInteger> ar = new ArrayList<BigInteger>();
int tot = Integer.parseInt(s.nextLine());
BigInteger max = BigInteger.ZERO;
for (int i = 0; i < tot; i++) {
String str[] = s.nextLine().split(" ");
Long n1 = Long.parseLong(str[0]);
Long r1 = Long.parseLong(str[1]);
Long nr1 = n1 - r1;
BigInteger n = BigInteger.valueOf(n1);
BigInteger r = BigInteger.valueOf(r1);
BigInteger nr = BigInteger.valueOf(nr1);
ar.add(n);
ar.add(r);
ar.add(nr);
if (n.compareTo(max)==1) {
max=n;
}
if (r.compareTo(max)==1) {
max=r;
}
if (nr.compareTo(max)==1) {
max=nr;
}
}
HashMap<BigInteger,BigInteger> m=new HashMap<BigInteger,BigInteger>();
m.put(BigInteger.ZERO, BigInteger.ONE);
BigInteger fact=BigInteger.ONE;
for(BigInteger i=BigInteger.ONE;i.compareTo(max.add(BigInteger.ONE))==-1;i=i.add(BigInteger.ONE)){
fact=fact.multiply(i);
if(ar.contains(i)){
m.put(i, fact);
}
}
for(int i=0;i<ar.size();i=i+3){
BigInteger n=m.get(ar.get(i));
BigInteger r=m.get(ar.get(i+1));
BigInteger nr=m.get(ar.get(i+2));
BigInteger rem=r.multiply(nr);
BigInteger act=n.divide(rem);
BigInteger res=act.remainder(BigInteger.valueOf(142857));
System.out.println(res);
}
}
}
I think this code might will help you .
Rather straightforward implementation:
public long combinations(int n, int k) {
BigInteger factorialN = factorial(n);
BigInteger factorialK = factorial(k);
BigInteger factorialNMinusK = factorial(n - k);
return factorialN.divide(factorialK.multiply(factorialNMinusK)).longValue();;
}
private BigInteger factorial(int n) {
BigInteger ret = BigInteger.ONE;
for (int i = 1; i <= n; ++i) ret = ret.multiply(BigInteger.valueOf(i));
return ret;
}
The part of your question about an exception with BigDecimal code isn't clear to me so I won't comment on that.
Regarding a sequence of multiplies and divides to compute nCr, wikipedia shows a formula that's easy to implement. Your first section of code in the question might be equivalent to it, as may be the bit of python code just below. It computes up to 61C30 using 64-bit integer arithmetic; 62C31 requires another bit or two.
def D(n, k):
c, j, k = 1, n, min(k,n-k)
for i in range(1,k+1):
c, j = c*j/i, j-1
return c
The reason that this order of computation works, with all divisions being exact divisions, is that nC(j+1) = nCj * (n-j)/(j+1) as is easily verified from nCj = n!/j!(n-j)! and some algebra. That is, you can compute nCr for large n and r completely in integer arithmetic without needing any decimal places.
Suppose K=142857.
Note that reduction of intermediate terms modulo K will cause problems and may be infeasible. If the numerator is reduced mod K, some divisions won't be exact in ordinary arithmetic. If K were prime, the extended GCD algorithm could be used to find inverses mod K for all numbers. But K=3*9*11*13*37 and inverses mod K will not exist for numbers that are multiples of 3, 11, 13, or 37, as a consequence of Bézout's lemma and some modular algebra.
You should not divide.
Draw Pascal triangle in memory. This will require only additions and will easily allow to apply modular arithmetic.
Also, this will last not longer than with divisions, because you can not avoid of calculating factorials.
package tests.StackOverflow;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class q13241166 {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String s;
String[] ss;
int[] n;
int[] r;
int T;
/*
System.out.println("Input T:");
s = in.readLine();
T = Integer.parseInt(s);
if( T < 1 || T > 100000) {
throw new IllegalArgumentException();
}
*/
T = 9;
/*
n = new int[T];
r = new int[T];
System.out.println("Input n r pairs:");
for(int i=0; i<T; ++i) {
s = in.readLine();
ss = s.split("\\s+");
n[i] = Integer.parseInt(ss[0]);
if( n[i] < 1 || n[i] > 1000000000) {
throw new IllegalArgumentException();
}
r[i] = Integer.parseInt(ss[1]);
if( r[i] < 0 || r[i] > n[i]) {
throw new IllegalArgumentException();
}
}
*/
n = new int[] {2, 4, 5, 10, 22, 24, 25, 16, 87};
r = new int[] {1, 0, 2, 3, 17, 17, 17, 15, 28};
int modulobase = 142857;
int[] answers_old, answers = null;
System.out.println("Output");
for(int i=0; i<T; ++i) {
for( int nn=0; nn<=n[i]; ++nn) {
answers_old = answers;
answers = new int[nn+1];
for( int rr=0; rr<=nn; ++rr) {
if( rr == 0 || rr == nn ) {
answers[rr] = 1;
}
else {
answers[rr] = answers_old[rr-1] + answers_old[rr];
}
answers[rr] %= modulobase;
}
}
System.out.println(answers[r[i]]);
}
}
}
Output follows:
Output
2
1
10
120
26334
60390
81576
16
141525