Using reverse() with BigInteger in java - java

I need to find the next palindrome of the input such that the number is not more than 1000000 DIGITS.
For this i am using BigInteger and I am getting "Time limit exceeded".
What to do now ?
import java.util.*;
import java.lang.*;
import java.io.*;
import java.math.BigInteger;
class Ideone
{
static boolean palindrome(BigInteger a)
{
String b=""+a;
StringBuffer s=new StringBuffer(b);
StringBuffer c=s.reverse();
String d=c.toString();
return d.equals(b);
}
public static void main (String[] args) throws java.lang.Exception
{
Scanner sc=new Scanner(System.in);
int t=sc.nextInt();
while(t-->0){
BigInteger k=sc.nextBigInteger();
try{for(BigInteger i=k.add(BigInteger.ONE);;i=i.add(BigInteger.ONE)){
if(palindrome(i)){System.out.println(""+i); break;}
}//for
}catch(Exception e){}
}//wh
}
}

Increasing numbers by BigInteger.ONE? That must be a joke for numbers with 1000000 digits...
Have you thought how long would it take?
Task spoiler (please ignore):
How about cutting the number to half number of digits and concatenate with this half reversed, and do one change when necessary? Would it be too difficult?
If you know, that the problem is time related, you shoud surround the code with some time measurement and logging. You should log how many digits you have and how much time does it take to verify the palindrome. And you should start with very small numbers first.

As V-X pointed out, there's no need for the whole incrementing business because we can turn things around: rather than checking which number is a palindrome, we can create palindromes first and test whether they're bigger than our target number.
Imagine that your number is 123456. What's the smallest palindrome that is bigger than it?
Is there a solution in the form 123xyz (x,y and z denote the missing digits)? There's only one palindromic number of that form: 123321. But because 123321<123456, that's not our answer.
So how about 124xyz? Following the same logic we find there's only one such number, 124421, which is greater than 123456.
Can there be any other palindromes in between? Since there are no numbers between 123999 and 124000, we've proven that there can't be.
Therefore our answer is 124421.
To sum it up what we did: we took the first half of the number (123456 -> 123), mirrored it (123 -> 123321), found that it's below our target, so we added 1 (123 -> 124) and mirrored it (124 -> 124421), and there's our answer. Had our initial number been something like 123004, we would've accepted 123321 as our answer straight away.
I'll leave it to you to work out what should happen when you've got an odd number of digits and in the case your number is in the form of 9999...9.
By the way, if you're testing for palindromes, there is no need to reverse the number. You can simply check whether the first digit equals the last digit, then compare the second to the second to last and so on. It'll be much, much faster as you only scan the string once.

You should try to minimise your use of BigInteger for this, because all the conversions between String and BigInteger take up unnecessary time. Just use next() instead of nextInt() to get each number from the scanner, and keep it as a String. Once you have the number, there are five cases to consider, which you could program in a series of if / else if blocks.
Case 1 - The input in invalid - it doesn't consist entirely of digits. It's not clear how you want to handle this, or whether you even want to bother.
Case 2 - The input consists entirely of nines. If there are n nines, then the next palindrome consists of a one, n-1 zeroes, and another one. For example, the next palindrome above 9999 is 10001.
Case 3 - The second half of the number, reversed, is less than the first half of the number. You can use string comparison for this - there's no need to convert anything to any numeric type. If there are an odd number of digits (say 2n+1) then you can round downwards (to n) when figuring out how many digits to examine. In this case, the next palindrome consists of the the first half of the number, then the middle digit if there is one, then the first half of the number reversed. For example, if the input is 5678123, then compare 567 to 321. Since 567 is greater, this case applies, and the output should be 5678765.
Case 4 - None of the other cases apply, even number of digits. Take the first half of the number and add one (and you can use BigInteger to do this step if you like). The output is the result of this, followed by its reversal. For example, if the input is 123789 then the first half of the number, with one added, is 124 and the output should be 124421.
Case 5 - None of the other cases apply, odd number of digits. Take the first half of the number; rounding upwards when figuring out how many digits to include. For example, if the input is 1234789, then take 1234. Now add one, then output the result, followed by the reversal of all but the last digit of the result. In this example, you'd output 1235 followed by the reversal of 123 - that is, 1235321. Just like case 4, you can use BigInteger for the addition.

Related

Keeping the "0" digit in front of a number

I'm making a small number reversal game. The user gets the 10 unique digits (0-9) in a random order, and has to put them in order by reversing them. However, when the 0 is in front such as:
0123456789 becomes 123456789
0000192837465 becomes 192837465
0(anything after) becomes (anything after)
The 0 disappears automatically. Any way to stop this? Since this number is constantly changing, I wish the 0 to simply stay in the number.
PS: In Java
Don’t represent the digits as a numeric type, use a string. After all your program is manipulating a string of characters, the individual characters happen to be digits but it’s not important that you evaluate it as a number.
When you write a program you need to consider your requirements and think of what data structure best handles them, when you use the first thing that comes to mind you can get yourself into trouble.

Getting exponents in a method without using Math.pow()

This was the problem I was given:
Create method lastDigit that is passed two positive integers. The first integer is the base and the second integer is the exponent. lastDigit will return the last digit of base^exponent. You need to think before you write your code. Hint: You do not need to actually find the product of base^exponent.
Then I need to use the method to find answer the questions below:
1) What is the last digit of 3^400?
2) What is the last digit of (3^0)(3^1)(3^2)(3^3)…(3^10)?
3) What is the last digit of the product of (3^0)(3^1)(3^2)…..(3^400)?
Here's the code that I wrote:
public static int lastDigit(int m, int n){
int p=1;
for(int i=1; i<=n; i++)
p=p*m;
return p%10;
}
However when I was trying to find the answers to the questions, I keep getting -1 for both the first and third questions, and 1 for the second question. Is there something wrong with the code, or how can I get the right answer?
You or a program you wrote may be suffering from Integer Overflow.
This is caused by chronic limitation of the int type.
Symptoms include
Negative integers that are really supposed to be positive
Small numbers that are supposed to be big
This condition can be controlled by ensuring that your int values don't exceed 2 billion.
If symptoms persist, see a debugger, or print out intermediate values.
*side effects may include frustration, throwing your computer out of a window, and/or deleting important system files.
But in all reality, let's say that you have a base of seven.
7=7
7*7=49
49*7=343
The last digit is 3.
However, if you, only take the last digit in between operations,
7*7 =49 -> 9
9*7 =63
The last digit is still three.
Doing this keeps the number well below the int limit.
This is actually what the p=(p*m)%10; solution is:
p= (p*m) %10
multiply the previous digit by the exponent take the last digit
The int variable is overflowing. Try changing p=p*m to p=(p*m)%10.

Sorting string so that there aren't two same characters on adjacent places [duplicate]

It's a bonus school task for which we didn't receive any teaching yet and I'm not looking for a complete code, but some tips to get going would be pretty cool. Going to post what I've done so far in Java when I get home, but here's something I've done already.
So, we have to do a sorting algorithm, which for example sorts "AAABBB" to the ABABAB. Max input size is 10^6, and it all has to happen under 1 second. If there's more than one answer, the first one in alphabetical order is the right one. I started to test different algorithms to even sort them without that alphabetical order requirement in mind, just to see how the things work out.
First version:
Save the ascii codes to the Integer array where index is the ascii code, and the value is amount which that character occurs in the char array.
Then I picked 2 highest numbers, and started to spam them to the new character array after each other, until some number was higher, and I swapped to it. It worked well, but of course the order wasn't right.
Second version:
Followed the same idea, but stopped picking the most occurring number and just picked the indexes in the order they were in my array. Works well until the input is something like CBAYYY. Algorithm sorts it to the ABCYYY instead of AYBYCY. Of course I could try to find some free spots for those Y's, but at that point it starts to take too long.
An interesting problem, with an interesting tweak. Yes, this is a permutation or rearranging rather than a sort. No, the quoted question is not a duplicate.
Algorithm.
Count the character frequencies.
Output alternating characters from the two lowest in alphabetical order.
As each is exhausted, move to the next.
At some point the highest frequency char will be exactly half the remaining chars. At that point switch to outputting all of that char alternating in turn with the other remaining chars in alphabetical order.
Some care required to avoid off-by-one errors (odd vs even number of input characters). Otherwise, just writing the code and getting it to work right is the challenge.
Note that there is one special case, where the number of characters is odd and the frequency of one character starts at (half plus 1). In this case you need to start with step 4 in the algorithm, outputting all one character alternating with each of the others in turn.
Note also that if one character comprises more than half the input then apart for this special case, no solution is possible. This situation may be detected in advance by inspecting the frequencies, or during execution when the tail consists of all one character. Detecting this case was not part of the spec.
Since no sort is required the complexity is O(n). Each character is examined twice: once when it is counted and once when it is added to the output. Everything else is amortised.
My idea is the following. With the right implementation it can be almost linear.
First establish a function to check if the solution is even possible. It should be very fast. Something like most frequent letter > 1/2 all letters and take into cosideration if it can be first.
Then while there are still letters remaining take the alphabetically first letter that is not the same as previous, and makes further solution possible.
The correct algorithm would be the following:
Build a histogram of the characters in the input string.
Put the CharacterOccurrences in a PriorityQueue / TreeSet where they're ordered on highest occurrence, lowest alphabetical order
Have an auxiliary variable of type CharacterOccurrence
Loop while the PQ is not empty
Take the head of the PQ and keep it
Add the character of the head to the output
If the auxiliary variable is set => Re-add it to the PQ
Store the kept head in the auxiliary variable with 1 occurrence less unless the occurrence ends up being 0 (then unset it)
if the size of the output == size of the input, it was possible and you have your answer. Else it was impossible.
Complexity is O(N * log(N))
Make a bi directional table of character frequencies: character->count and count->character. Record an optional<Character> which stores the last character (or none of there is none). Store the total number of characters.
If (total number of characters-1)<2*(highest count character count), use the highest count character count character. (otherwise there would be no solution). Fail if this it the last character output.
Otherwise, use the earliest alphabetically that isn't the last character output.
Record the last character output, decrease both the total and used character count.
Loop while we still have characters.
While this question is not quite a duplicate, the part of my answer giving the algorithm for enumerating all permutations with as few adjacent equal letters as possible readily can be adapted to return only the minimum, as its proof of optimality requires that every recursive call yield at least one permutation. The extent of the changes outside of the test code are to try keys in sorted order and to break after the first hit is found. The running time of the code below is polynomial (O(n) if I bothered with better data structures), since unlike its ancestor it does not enumerate all possibilities.
david.pfx's answer hints at the logic: greedily take the least letter that doesn't eliminate all possibilities, but, as he notes, the details are subtle.
from collections import Counter
from itertools import permutations
from operator import itemgetter
from random import randrange
def get_mode(count):
return max(count.items(), key=itemgetter(1))[0]
def enum2(prefix, x, count, total, mode):
prefix.append(x)
count_x = count[x]
if count_x == 1:
del count[x]
else:
count[x] = count_x - 1
yield from enum1(prefix, count, total - 1, mode)
count[x] = count_x
del prefix[-1]
def enum1(prefix, count, total, mode):
if total == 0:
yield tuple(prefix)
return
if count[mode] * 2 - 1 >= total and [mode] != prefix[-1:]:
yield from enum2(prefix, mode, count, total, mode)
else:
defect_okay = not prefix or count[prefix[-1]] * 2 > total
mode = get_mode(count)
for x in sorted(count.keys()):
if defect_okay or [x] != prefix[-1:]:
yield from enum2(prefix, x, count, total, mode)
break
def enum(seq):
count = Counter(seq)
if count:
yield from enum1([], count, sum(count.values()), get_mode(count))
else:
yield ()
def defects(lst):
return sum(lst[i - 1] == lst[i] for i in range(1, len(lst)))
def test(lst):
perms = set(permutations(lst))
opt = min(map(defects, perms))
slow = min(perm for perm in perms if defects(perm) == opt)
fast = list(enum(lst))
assert len(fast) == 1
fast = min(fast)
print(lst, fast, slow)
assert slow == fast
for r in range(10000):
test([randrange(3) for i in range(randrange(6))])
You start by count each number of letter you have in your array:
For example you have 3 - A, 2 - B, 1 - C, 4 - Y, 1 - Z.
1) Then you put each time the lowest one (it is A), you can put.
so you start by :
A
then you can not put A any more so you put B:
AB
then:
ABABACYZ
These works if you have still at least 2 kind of characters. But here you will have still 3 Y.
2) To put the last characters, you just go from your first Y and insert one on 2 in direction of beginning.(I don't know if these is the good way to say that in english).
So ABAYBYAYCYZ.
3) Then you take the subsequence between your Y so YBYAYCY and you sort the letter between the Y :
BAC => ABC
And you arrive at
ABAYAYBYCYZ
which should be the solution of your problem.
To do all this stuff, I think a LinkedList is the best way
I hope it help :)

Representing large numbers using linked lists and performing operations

I need to store two extremely large numbers (Strings, since they won't fit in int) in two linked lists, add them and then display the result (again, a String).
I can store the numbers directly into the list.
312312 can be stored as 2->1->3->2->1->3 (actual number will be extremely long)
111119 can be stored as 9->1->1->1->1->1
Then I can add them
11->2->4->3->2->4
Normally I could do 11*10^0 + 2*10^1 +...+ 4*10^5 and get 423431 but all those operations (multiplication, addition and exponentiation) would again be integer operations and since the actual numbers are going to be extremely big, int or long won't support the operations. The final result has to be a string.
So I need a way to convert 11->2->4->3->2->4 into 423431 without using int. Also, I cannot use BigInteger. Can anyone help me?
Well, first thing you need to do is implement carry.
For each digit (that is >= 10), you need to increase the next digit by that digit /10 and set that digit to that digit %10.
So 11->2->... becomes 1->3->....
Then to actually produce the string.
For the most performant option, I suggest StringBuilder.
Just append each digit in the linked-list, then just reverse().toString() (since you started with the smallest number).
Think about how you would do it by hand on paper. If the sum of a pair digits is greater than 9 you write down a carry digit of 1, which you add into the sum of the next pair of digits.
In a computer program you can use a local variable for that: add digits from first and last numbers and the carry from earlier, if sum is greater than.. set carry to 1, else set carry to 0, move on to the next pair...

How to get the last digits of 2 power

I’m working on a problem where its demanded to get the last 100 digits of 2^1001. The solution must be in java and without using BigInteger, only with int or Long. For the moment I think to create a class that handle 100 digits. So my question is, if there is another way the handle the overflow using int or long to get a number with 100 digits.
Thanks for all.
EDITED: I was off by a couple powers of 10 in my modulo operator (oops)
The last 100 digits of 2^1001 is the number 2^1001 (mod 10^100).
Note that 2^1001 (mod 10^100) = 2*(2^1000(mod 10^100)) (mod 10^100).
Look into properties of modulo: http://www.math.okstate.edu/~wrightd/crypt/lecnotes/node17.html
This is 99% math problem, 1% programming problem. :)
With this approach, though, you wouldn't be able to use just an integer, as 10^100 won't fit in an int or long.
However, you could use this to find, say, the last 10 digits of 2^1001, then use a separate routine to find the next 10 digits, etc, where each routine uses this feature...
The fastest way to do it (coding wise) is to create an array of 100 integers and then have a function which starts from the ones place and doubles every digit. Make sure to take the modulus of 10 and carry over 1s if needed. For the 100th digit, simply eliminate the carry over. Do it 1001 times and you're done.

Categories