Cutting of the first 9 digits - java

Alright I am trying to solve a challenge one of my friends gave me to do, well I've manged to cut the last 9 digits out of a BigInteger well I had a way to cut-off the first 9 but it was so slow, it was taking too long.
The reason I need the first 9 and the last 9 is because I am looking for a BigInteger where the first and last are pandigital.
If you do not understand what I mean say we have n = new BigInteger("123456789987654321") well I need to get the "123456789" and the "987654321" seperately, and I do NOT want to convert the BigInteger to a string because that's a VERY slow process.
I am going for speed here, I am just stumped on this solution. I've heard something about using the Golden Ratio? Here is my code if you're interested.
import java.math.BigInteger;
public class Main {
public static void main(String...strings)
{
long timeStart = System.currentTimeMillis();
fib(350_000);
long timeEnd = System.currentTimeMillis();
System.out.println("Finished processing, time: " + (timeEnd - timeStart) + " milliseconds.");
}
public static BigInteger fib(int n)
{
BigInteger prev1 = BigInteger.valueOf(0), prev2 = BigInteger.valueOf(1);
for (int i = 0; i < n; i++)
{
// TODO: Check if the head is pandigital as well.
BigInteger tailing9Digits = tailing9Digits(prev1);
boolean tailPandigital = isPanDigital(tailing9Digits);
if (tailPandigital)
{
System.out.println("Solved at index: " + i);
break;
}
BigInteger savePrev1 = prev1;
prev1 = prev2;
prev2 = savePrev1.add(prev2);
}
return prev1;
}
public static BigInteger leading9Digits(BigInteger x)
{
// STUCK HERE.
return null;
}
public static BigInteger tailing9Digits(BigInteger x)
{
return x.remainder(BigInteger.TEN.pow(9));
}
static BigInteger[] pows = new BigInteger[16];
static
{
for (int i = 0; i < 16; i++)
{
pows[i] = BigInteger.TEN.pow(i);
}
}
static boolean isPanDigital(BigInteger n)
{
if (!n.remainder(BigInteger.valueOf(9)).equals(BigInteger.ZERO))
{
return false;
}
boolean[] foundDigits = new boolean[9];
boolean isPanDigital = true;
for (int i = 1; i <= 9; i++)
{
BigInteger digit = n.remainder(pows[i]).divide(pows[i - 1]);
for (int j = 0; j < foundDigits.length; j++) {
if (digit.equals(BigInteger.valueOf(j + 1)) && !foundDigits[j])
{
foundDigits[j] = true;
}
}
}
for (int i = 0; i < 9; i++)
{
isPanDigital = isPanDigital && foundDigits[i];
}
return isPanDigital;
}
}

BigInteger isn't something I'd recommend using if you care at all about speed. Most of its methods are poorly-implemented, and this typically results in very slow code.
There's a divide-and-conquer trick for division and radix conversion that you might find helpful.
First, BigInteger's multiply() is quadratic. You'll need to work around that, otherwise these divide-and-conquer tricks won't lead to any speedup. Multiplication via the fast Fourier transform is reasonably fast and good.
If you want to convert a BigInteger to base 10, break it in half (bitwise) and write it as a * 256^k + b. One thing you can do is convert a and b to base-10 recursively, then convert 256^k to decimal by repeated squaring, and then, in base 10, multiply a by 256^k and add b to the result. Also, since you're only interested in the first few digits, you might not even need to convert b if the first few digits of a * 256^k can't possibly be influenced by adding something as small as b.
A similar trick works for division.
You can do bit-shifting and extraction using the toByteArray() method.

Well I believe this is what you need:
import java.math.BigInteger;
public class PandigitalCheck {
public static void main(String[] args) {
BigInteger num = new BigInteger("12345678907438297438924239987654321");
long timeStart = System.currentTimeMillis();
System.out.println("Is Pandigital: " + isPandigital(num));
long timeEnd = System.currentTimeMillis();
System.out.println("Time Taken: " + (timeEnd - timeStart) + " ms");
}
private static boolean isPandigital(BigInteger num) {
if (getTrailing9Digits(num).compareTo(getLeading9Digits(num)) == 0) {
return true;
}
return false;
}
private static BigInteger getLeading9Digits(BigInteger num) {
int length = getBigIntLength(num);
BigInteger leading9 = BigInteger.ZERO;
for (int i = 0; i < 9; i++) {
BigInteger remainder = num.divide(BigInteger.TEN.pow(length - 1 - i));
leading9 = leading9.add(remainder.multiply(BigInteger.TEN.pow(i)));
num = num.remainder(BigInteger.TEN.pow(length - 1 - i));
}
return leading9;
}
private static int getBigIntLength(BigInteger num) {
for (int i = 1; ; i++) {
if (num.divide(BigInteger.TEN.pow(i)) == BigInteger.ZERO) {
return i;
}
}
}
private static BigInteger getTrailing9Digits(BigInteger num) {
return num.remainder(BigInteger.TEN.pow(9));
}
}
The output is:
Is Pandigital: true
Time Taken: 0 ms
Does it fit the bill?

I’m newbie for java, I’m converting BigInteger to String only but it's little bit fast as your code
import java.math.BigInteger;
public class Main {
public static void main(String args[])
{
long timeStart = System.currentTimeMillis();
String biStr = new BigInteger("123456789987654321").toString();
int length=(biStr.length())/2;
String[] ints = new String[length];
String[] ints2 = new String[length];
for(int i=0; i<length; i++) {
int j=i+length;
ints[i] = String.valueOf(biStr.charAt(i));
ints2[i] = String.valueOf(biStr.charAt(j));
System.out.println(ints[i] +" | "+ints2[i]);
}
long timeEnd = System.currentTimeMillis();
System.out.println("Finished processing, time: " + (timeEnd - timeStart) + " milliseconds.");
}
}

Maybe this is not too fast but at least it's simple
BigInteger n = new BigInteger("123456789987654321");
BigInteger n2 = n.divide(BigInteger.TEN.pow(new BigDecimal(n).precision() - 9));
BigInteger n1 = n.remainder(new BigInteger("1000000000"));
System.out.println(n1);
System.out.println(n2);
output
987654321
123456789

Related

Interview Programming question?(Long bit representation)?

Given a long number n, we need to return a long number which we get from the concatenation of binary representation from 1 to n?
Example say n=3, then answer would be 27, as 1 in binary is 01, 2 is 10 and 3 is 11 so concatenation would be 011011 which is 27.
this is the approach I used,
class Solution {
static String[] arr;
public static long binaryArray(long A) {
String res = "";
for (long i = 1; i <= A; i++) {
res += toBinary(i);
}
long rest = toLong(res);
return rest % 1000000007;
}
static long toLong(String s) {
int a = s.length();
int pow = 0;
long res = 0;
for (int i = a - 1; i >= 0; i--) {
char aa = s.charAt(i);
long f = Character.getNumericValue(aa);
long power = (long) Math.pow(2, pow);
res += power * f;
pow++;
}
return res;
}
static String toBinary(long a) {
if (a == 0) {
return "0";
}
String binary = "";
binary = Long.toBinaryString(a);
return binary;
}
public static void main(String args[]) {
long n = 89900;
arr = new String[(int) n + 1];
arr[0] = "0";
long startTime = System.nanoTime();
long b = binaryArray(n);
long endTime = System.nanoTime();
long totalTime = endTime - startTime;
long convert = TimeUnit.SECONDS.convert(totalTime, TimeUnit.NANOSECONDS);
System.out.println(convert);
System.out.println(b);
}
}
but it is not completing the request in the required time.
Is there a quicker way?
public static long f(int n) {
long n2 = ((long)n) << n;
return n2 | n;
}
There is much irrelevant text in the specification: binary representation, concatenation and such. What is said:
the bits of n should be "concatenated" n bits to the left = bit shift.
So this interview question was intentionally misleading, and the actual solution simple. It tried and succeeded to let the interviewee start with bit tests and such.
Now I am somewhat experienced and the trick is always to look at the whole picture,
think in notions like sets, or Integer's bit functions.
As #kaya3 commented, the following might be more correct.
public static long f(int n) {
long n2 = 0;
for (int i = 0; i < n; ++i) {
if ((n & (1 << i)) == 1) { // i'th bit set?
int bits = 32 - Integer.numberOfLeadingZeros(i);
n2 <<= bits;
n2 |= i;
}
}
return n2;
}

PalindromeCheck efficiency for Int in Java

I have constructed two ways to check palindrome of a number. Which one is more efficient? By efficiency, I mean in terms of execution time and memory allocations.
First, I convert an Integer to string and check if it is a palindrome. The example of code is as follow.
public class Palindrome{
/*
Function palindromeCheck
Return type boolean
Parameters characterArray
Checks character array for palindrome
*/
public static boolean palindromeCheck(char[] palinCheck){
boolean palindrome = true;
int firstLen = 0;
int secondLen = palinCheck.length - 1;
while(palindrome == true && firstLen < secondLen ){
if(palinCheck[firstLen] != palinCheck[secondLen]){
palindrome = false;
}
else{
firstLen++;
secondLen--;
}
} //end of while
return palindrome;
}
/*Main Function
Calls palinDromeCheck function
Prints results
*/
public static void main(String[] args){
int palinCheck = 1221;
String dipendra = Integer.toString(palinCheck);
char[] dipendraChar = dipendra.toCharArray();
System.out.println(palindromeCheck(dipendraChar));
}
}
The second method is without converting it to string.
public class PalindromeNumber{
/*
Function: PalindromeCheck
parameters integer
ReturnType: boolean
Takes integer, checks if it is palindrome and returns accordingly
*/
public static boolean palindromeCheck(int number){
int firstNumber = number;
int secondNumber = 0;
while(number >= 1){
secondNumber = secondNumber* 10 + (number%10);
number = number/10;
}
return (firstNumber==secondNumber) ? true:false;
}
public static void main(String[] args){
System.out.println(palindromeCheck(111));
}
}
I bet the second algorithm would be faster, and obviously more space efficient. If you assume n be the number of digits of the input number, in the first algorithm:
Integer.toString requires n steps to convert it to String.
palindromeCheck requires n / 2 comparisons to check whether it's a palindrome.
But, the second algorithm would require n steps to compute the reverse number (involving only integer operations) and only 1 comparison to check.
Let's try.
On the following example (with one specific number, on my specific machine...) :
580 ms - Your first solution
323 ms - Your second solution
1045 ms - BrentR's solution
Note I modified the code a bit (but not the logic). You should also take care of spaces and indentation.
public class Palindrome {
public static boolean isPalindrome1(int n) {
char a[] = Integer.toString(n).toCharArray();
int i = 0;
int j = a.length - 1;
while (i < j) {
if (a[i++] != a[j--]) return false;
}
return true;
}
public static boolean isPalindrome2(int n) {
int p = n, q = 0;
while (n > 0) {
q = 10 * q + n % 10;
n /= 10;
}
return p == q;
}
public static boolean isPalindrome3(int n) {
String s = Integer.toString(n);
return s.equalsIgnoreCase(new StringBuilder(s).reverse().toString());
}
public static void main(String[] args) {
final int m = 10000000;
long t1, t2;
boolean q;
t1 = System.currentTimeMillis();
for (int n = 0; n < m; n++) {
q = isPalindrome1(123454321);
}
t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
t1 = System.currentTimeMillis();
for (int n = 0; n < m; n++) {
q = isPalindrome2(123454321);
}
t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
t1 = System.currentTimeMillis();
for (int n = 0; n < m; n++) {
q = isPalindrome3(123454321);
}
t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
}
}
Why are you re-inventing the wheel?
java.lang.StringBuilder already provides a string reverse method
String string = Integer.toString(10101);
boolean palindrome = string.equalsIgnoreCase(new StringBuilder(string).reverse().toString());

Summing up huge fibonacci numbers (upto 10^18)

I recently came across a problem where given a l and r you need to find out the sum of all x such that l <= x <= r (mod10^9 + 7).
And,
1 <= l <= r <= 10^18
Let sum(x) be the sum of fibonacci numbers upto x and let fibo(x) be the xth fibonacci number. It is known that
sum(x) = fibo(x+2) - 1
Using this I used this post to calculate the nth fibonacci term in O(logn) time.
I was wondering if it can be done any faster than this. Below is my implementation
public class FastFibonacci {
private static Map<BigInteger, BigInteger> map;
private static BigInteger mod = BigInteger.valueOf(1000000007);
public static BigInteger nthFibonacci(BigInteger num) {
if (num.compareTo(BigInteger.valueOf(2)) <= 0) return BigInteger.ONE;
return solve(num.subtract(BigInteger.ONE)).mod(BigInteger.valueOf(10000));
}
public static BigInteger solve(BigInteger num) {
if (map.get(num) != null) {
return map.get(num);
} else {
BigInteger k = num.divide(BigInteger.valueOf(2));
if (num.mod(BigInteger.valueOf(2)).compareTo(BigInteger.ZERO) == 0) {
// f(2*k)
map.put(num, (solve(k).multiply(solve(k)).mod(mod).add(solve(k.subtract(BigInteger.ONE)).multiply(solve(k.subtract(BigInteger.ONE))).mod(mod)).mod(mod)));
return map.get(num);
} else {
// f(2*k + 1)
map.put(num, (solve(k).multiply(solve(k.add( BigInteger.ONE))).mod(mod).add(solve(k).multiply(solve(k.subtract(BigInteger.ONE))).mod(mod))).mod(mod));
return map.get(num);
}
}
}
public static void main(String[] args) {
InputReader in = new InputReader(System.in);
map = new HashMap<>();
map.put(BigInteger.ZERO, BigInteger.ONE);
map.put(BigInteger.ONE, BigInteger.ONE);
int test = in.nextInt();
BigInteger[] ls = new BigInteger[test];
BigInteger[] rs = new BigInteger[test];
for (int i = 0; i < test; i++) {
ls[i] = new BigInteger(in.readString());
rs[i] = new BigInteger(in.readString());
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < test; i++) {
BigInteger sumUptoL = nthFibonacci(ls[i]).subtract(BigInteger.ONE);
BigInteger sumUptoR = nthFibonacci(rs[i].add(BigInteger.valueOf(1))).subtract(BigInteger.ONE);
sb.append(sumUptoR.subtract(sumUptoL));
sb.append("\n");
}
System.out.print(sb.toString());
}
}
Assuming that for a given number N you only want to know fib(N+2)-1 and you don't really need to show all the sequence, you can use a non-recursive approach. The following function uses double, but you can refactor it to BigInteger to accept bigger values:
public double getFibonacci(int n) {
double f1 = Math.pow(((1 + Math.sqrt(5)) / 2.0), n);
double f2 = Math.pow(((1 - Math.sqrt(5)) / 2.0), n);
return Math.floor((f1 - f2) / Math.sqrt(5));
}

Wordlist generator that support BigIntegers for Huge Numbers

I need a help to complete a program that will generate a wordlist from chosen characters and length (it need to support a big length).
At first you need to fix this both by adding the length (wordlength) wanted and making a string of the specified characters(alphabet).
So the full number of words is:
long MAX_WORDS = (long) Math.pow(alphabet.length(), wordlength);
Actually, I made it and it work (for the example of short word of 2 or 66 characters).
import java.math.BigInteger;
public class wordlistgenenreg {
public static void main(String[] args) {
generate();
}
private static void generate(){
int wordlength =2;
String alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~";
final long MAX_WORDS = (long) Math.pow(alphabet.length(), wordlength);
final int RADIX = alphabet.length();
for (long i = 0; i < MAX_WORDS; i++) {
int[] indices = convertToRadix(RADIX, i, wordlength);
char[] word = new char[wordlength];
for (int k = 0; k < wordlength; k++) {word[k] = alphabet.charAt(indices[k]);}
String fullword=new String(word);
System.out.println(fullword);
}
System.out.println("completed!");
}
private static int[] convertToRadix(int radix, long number, int wordlength) {
int[] indices = new int[wordlength];
for (int i = wordlength - 1; i >= 0; i--) {
if (number > 0) {
int rest = (int) (number % radix);
number /= radix;
indices[i] = rest;
} else {
indices[i] = 0;
}
}
return indices;
}
}
but there are a problem when i want to generate a really big string of 64 characters from 66. Because:
MAX_WORDS = 66^64 = 282365657377235405270307754780751252031361330095689004197961218014051357270480550051149871489969454245263206971867136
So I tried to change it to make it work with the BigInteger. But us a result, I always obtain the String:
"0000000000000000000000000000000000000000000000000000000000000000"
So there are a problem that i didn't figure it out. This my work on changing it:
import java.math.BigInteger;
public class wordlistgen {
public static void main(String[] args) {
generate();
}
private static void generate() {
int wordlength = 64;
String alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~";
BigInteger max_words=new BigInteger("282365657377235405270307754780751252031361330095689004197961218014051357270480550051149871489969454245263206971867136");
final int RADIX = alphabet.length();
BigInteger plus=BigInteger.valueOf(1);
for (BigInteger i = new BigInteger("0"); i.compareTo(max_words) <0; i.add(plus)) {
int[] indices = convertToRadix(RADIX, i, wordlength);
char[] word = new char[wordlength];
for (int k = 0; k < wordlength; k++) {word[k] = alphabet.charAt(indices[k]);}
String fullword=new String(word);
System.out.println(fullword);
}
}
private static int[] convertToRadix(int radix, BigInteger i2, int wordlength) {
BigInteger zero=BigInteger.valueOf(0);
BigInteger big_radix=BigInteger.valueOf(radix);
int[] indices = new int[wordlength];
for (int i = wordlength - 1; i >= 0; i--) {
if (i2.compareTo(zero)==0) {
BigInteger rest =i2.remainder(big_radix);
BigInteger ab=i2.divide(big_radix);
i2=ab;
indices[i] = rest.intValue();
} else {
indices[i] = 0;
}
}
return indices;
}
}
This is the if from your original version:
if (number > 0) {
int rest = (int) (number % radix);
number /= radix;
indices[i] = rest;
} else {
indices[i] = 0;
}
And the same if in the BigInteger version:
if (i2.compareTo(zero)==0) {
BigInteger rest =i2.remainder(big_radix);
BigInteger ab=i2.divide(big_radix);
i2=ab;
indices[i] = rest.intValue();
} else {
indices[i] = 0;
}
As you can see, in your new if, you are asking if number == 0 instead of number > 0. So you always end up in the else.
As a side note: you are running a loop from 0 to your max_words. If each iteration takes merely a nanosecond to complete, it will still take 368788667672120349090672500612638816231217766896306723928560063188563281831044121479026746095987887263264265 years. Enough time for the universe to disintegrate into full entropy. I'd suggest re-thinking your algorithm.

Class assignment requires me to have two versions of the same code. This one, and one using BigInteger. Need help converting to BigInteger

I am required specifically to use BigInteger in place of long. This is so if the fibonacci number is too large, it won't return a negative. We haven't done some of the more complicated functions that java has built in, so I'm going to have to do it as simple as possible.
import java.util.Scanner;
public class FibBigInt{
public static long fib_l(int n){
long result = 0;
long f0 = 1, f1 = 1;
while(n > 0){
f0 = f1;
f1 = result;
result = f0 + f1;
n--;
}
return result;
}
public static long fib_r(int n){
long result = 1;
if(n <= 2){
return result;
}
else{
result = fib_r(n - 1) + fib_r(n - 2);
}
return result;
}
public static long fval[];
public static long fib_r_Memo(int n){
long result = 1;
if(n > 2) {
if(fval[n] != 0){
result = fval[n];
}
else{
result = fib_r_Memo(n - 1) + fib_r_Memo(n - 2);
fval[n] = result;
}
}
return result;
}
public static void main(String [] args){
Scanner s = new Scanner(System.in);
System.out.print("Please enter an integer: ");
int n = s.nextInt();
long t1 = System.currentTimeMillis();
//System.out.println("Fibonacci number " + n + " is " + fib_l(n));
//System.out.println("Fibonacci number " + n + " is " + fib_r(n));
fval = new long[n + 1];
for(int i = 0; i < fval.length; ++i){
fval[i] = 0;
}
System.out.println("Fibonacci number " + n + " is " + fib_r_Memo(n));
long t2 = System.currentTimeMillis();
System.out.println("Elapsed time: " + (t2 - t1)/1000 + " seconds. ");
}
}
Here is an example recursive BigInteger version using a memoization optimization and supporting the "negafibonacci",
private static Map<Integer, BigInteger> memo = new TreeMap<>();
private static final BigInteger NEGATIVE_ONE = new BigInteger("-1");
public static BigInteger fib(final int n) {
if (n < 0) {
// This if block adds the "negafibonacci" support.
final int p = Math.abs(n);
final boolean even = p % 2 == 0;
if (even) {
return NEGATIVE_ONE.multiply(fib(p));
}
return fib(p);
} else if (n == 0) {
return BigInteger.ZERO;
} else if (n == 1 || n == 2) {
return BigInteger.ONE;
}
if (memo.containsKey(n)) {
return memo.get(n);
}
BigInteger r = fib(n - 1).add(fib(n - 2));
memo.put(n, r);
return r;
}
public static void main(String[] args) {
for (int i = -8; i <= 8; i++) {
System.out.println(fib(i).toString());
}
}
When I run the above I get a sequence that matches the one from Wikipedia -
−21 13 −8 5 −3 2 −1 1 0 1 1 2 3 5 8 13 21
Finally, I created a simple benchmark -
public static void main(String[] args) {
long current = System.currentTimeMillis();
for (int i = 1; i < 1000; i++) {
System.out.println(fib(i));
}
long end = System.currentTimeMillis();
System.out.printf("Ran in: %d milliseconds", end - current);
}
When I calculate the first 999 fibonacci numbers it completes in under 200 milliseconds. If you really wanted to optimize further you could look into the Closed-form Expression.

Categories

Resources