Combining numbers into one Java variable - java

I am trying to make a program that, depending on an int called length, adds a certain number of 9s to a variable called nines. For example, if length is 4 then I want nines to equal 9999. If length is 7, I want nines to equal 9999999. The value of length needs to correspond to the number of nines in nines. Is this possible, and if so, how?

Yes, it is possible: observe that your target number is ten to the power of Length, minus one:
int res = Math.pow(10, length) - 1;

You could do this:
StringBuilder sb = new StringBuilder();
while (length-- > 0) {
sb.append('9');
]
nines = sb.toString();
Or, if nines is an int:
nines = 0;
while (length-- > 0) {
nines = 10 * nines + 9;
}

The simplest way:
String nines = "";
for(int i = 0; i < length; i++) {
nines += "9";
}
return Integer.parseInt(nines);

You can do this by creating a String with the correct number of numerical characters, then parse it into an int. Something like this...
String bigNumber = "";
for (int i=0;i<length;i++){
bigNumber += "9";
}
int intNumber = Integer.parseInt(bigNumber);
However, note that there are limits to the size of the int. I would recommend that you...
Perhaps try using something that can hold larger numbers, such as long (realising that long still has a limit, but its a higher limit than int).
Provide error checking - if there are too many characters or the number is too big, show an error to the user, rather than crashing your application.

Since we're at it...
char[] nineChars = new char[length];
Arrays.fill(nineChars, '9');
String nines = new String(nineChars);

If you're not opposed to including another library, you could use Apache Commons Lang StringUtils.repeat http://commons.apache.org/lang/api-release/org/apache/commons/lang3/StringUtils.html#repeat(char, int)
String nines = StringUtils.repeat('9',length);

Related

Can i decrease the time complexity using dynamic programming?

I have an array of Strings and among them one string is,
String s = "66678889966";
and I need to output it as 60078009060
i.e; I am making consecutive repeated chars as zero keeping the starting char.
Not only that string, all other strings as well, so I can't avoid outer loop to iterate over all those strings.
I solved this using a naive approach. Actually, I am solving a problem that includes another loop with an array of strings like this. Including my inner loop, it goes up to O(n^2) which is not acceptable.
BufferedReader bf = new BufferedReader(newInputStreamReader(System.in));
String s[], s1[];
s = bf.readLine().trim().split("\\s+");
s1 = bf.readLine().trim().split("\\s+");
BigInteger sb = new BigInteger(s[1]);
BigInteger sb1 = new BigInteger(s1[1]);
BigInteger indexIncre = new BigInteger("1");
BigInteger first = new BigInteger(s[1]);
BigInteger last = new BigInteger(s1[1]);
BigInteger length = last.subtract(first);
BigInteger summation = new BigInteger("0");
for (index = new BigInteger("0");
!index.subtract(length).toString().equals("1");
index =index.add(indexIncre)) {
StringBuilder str = new StringBuilder(first.toString());
int len = str.length();
char c = str.charAt(0);
for (int i = 1; i < len; i++) {
if (str.charAt(i) == c) {
str.setCharAt(i, '0');
} else
c = str.charAt(i);
}
first = first.add(indexIncre);
summation = summation.add(new BigInteger(str.toString()));
}
BigInteger modulo = BigInteger.valueOf((long) Math.pow(10, 9) + 7);
System.out.println(summation.mod(modulo));
For example
Input
1 8
2 12
output
49
This is in the form of
Input
NL L
NR R
The range of NL,L,NR,R are
1≤NL,NR≤10^5
1≤L≤R<10^100,000
Modified value is f(x)
f(8)=8,f(9)=9,f(10)=10,f(11)=10,f(12)=12
and modulo the sum of all these f(x) by 10^9+7
NL is the length of left-most string and L is the string, NR is the length of right most string and R is right most string. For example in the question length of number string 8 is 1 and the length of number string 12 is 2. The total number of strings are 8,9,10,11,12
You have a total of 'n' strings. Let's assume they are of an average 'm' length.
You will have to touch each character of each string at least once in order to know whether you have to zero out that particular character or not. Therefore the best complexity that you can achieve is O(m * n), which is quadratic.
O(m * n) is the same complexity that you would get by iterating in nested loop approach. Hence, you cannot do better than that by employing dynamic programming/memoization.

Split Array without delimiters?

Is there a better(Faster) way to split a binary string into an Array?
My code That loops and substring every 8 characters in one element.
binary = my binary string(Huge) : "1010101011111000001111100001110110101010101"
int index = 0;
while (index < binary.length()) {
int num = binaryToInteger(binary.substring(index, Math.min(index + 8,binary.length())));
l.add( num);
temp = temp+ String.valueOf(num);
index += 8;
}
What I am trying to do is to split my binary string into pieces of 8 characters 10101010 and then get the int value of the 8 characters and will store that in arraylist witch in this case was l
My code is working but is very time consuming.. Is there a faster way of getting this done?
It's easy using regex:
binary.split("(?<=\\G.{8})");
However, it creates an array of strings. I don't get your will of creating an array of integers, since binary strings don't fit into this type (they can start with "0" and they can be really long).
I think there are mutiple options using Regex, substring, split etc available in java or Google Guavas - Splitter.fixedLength().
Splitter.fixedLength(8).split("1010101011111000001111100001110110101010101");
This Split a string, at every nth position clearly explain the performance of various functions.
It would probably faster using toCharArray:
Long time = System.currentTimeMillis();
List<Integer> l = new ArrayList<>();
int index = 0;
String binary =
"1010101011111000001111100001110110101";
char[] binaryChars = binary.toCharArray();
while (index < binaryChars.length) {
int num = 0;
for (int offset = 0; offset < Math.min(8, binary.length() - index); offset++) {
int bo = index + offset;
if (binaryChars[bo] == '1') {
num += Math.pow(2, offset + 1);
}
}
l.add(num);
index += 8;
}
System.out.println(System.currentTimeMillis() - time);
Since you want to split into groups of eight bits, I guess, you want to decode bytes rather than ints. This is easier than you might think:
String binary = "1010101011111000001111100001110110101010101";
byte[] result=new BigInteger(binary, 2).toByteArray();
Maybe you can try making a for-each loop to go through each character in the string, combine them into 8-bit values and convert into bytes. I don't know if that will be faster, just a suggestion.
for (char c : binary.toCharArray() ) { do stuff }

int array to int number in Java

I'm new on this site and, if I'm here it's because I haven't found the answer anywhere on the web and believe me: I've been googling for quite a time but all I could find was how to convert a number to an array not the other way arround.
I'm looking for a simple way or function to convert an int array to an int number. Let me explain for example I have this :
int[] ar = {1, 2, 3};
And I want to have this:
int nbr = 123;
In my head it would look like this (even if I know it's not the right way):
int nbr = ar.toInt(); // I know it's funny
If you have any idea of how I could do that, that'd be awesome.
Start with a result of 0. Loop through all elements of your int array. Multiply the result by 10, then add in the current number from the array. At the end of the loop, you have your result.
Result: 0
Loop 1: Result * 10 => 0, Result + 1 => 1
Loop 2: Result * 10 => 10, Result + 2 => 12
Loop 3: Result * 10 >= 120, Result + 3 => 123
This can be generalized for any base by changing the base from 10 (here) to something else, such as 16 for hexadecimal.
You have to cycle in the array and add the right value.
The right value is the current element in the array multiplied by 10^position.
So: ar[0]*1 + ar[1]*10 + ar[2] *100 + .....
int res=0;
for(int i=0;i<ar.length;i++) {
res=res*10+ar[i];
}
Or
for(int i=0,exp=ar.length-1;i<ar.length;i++,exp--)
res+=ar[i]*Math.pow(10, exp);
First you'll have to convert every number to a string, then concatenate the strings and parse it back into an integer. Here's one implementation:
int arrayToInt(int[] arr)
{
//using a Stringbuilder is much more efficient than just using += on a String.
//if this confuses you, just use a String and write += instead of append.
StringBuilder s = new StringBuilder();
for (int i : arr)
{
s.append(i); //add all the ints to a string
}
return Integer.parseInt(s.toString()); //parse integer out of the string
}
Note that this produce an error if any of the values past the first one in your array as negative, as the minus signs will interfere with the parsing.
This method should work for all positive integers, but if you know that all of the values in the array will only be one digit long (as they are in your example), you can avoid string operations altogether and just use basic math:
int arrayToInt(int[] arr)
{
int result = 0;
//iterate backwards through the array so we start with least significant digits
for (int n = arr.length - 1, i = 1; n >= 0; n --, i *= 10)
{
result += Math.abs(arr[n]) * i;
}
if (arr[0] < 0) //if there's a negative sign in the beginning, flip the sign
{
result = - result;
}
return result;
}
This version won't produce an error if any of the values past the first are negative, but it will produce strange results.
There is no builtin function to do this because the values of an array typically represent distinct numbers, rather than digits in a number.
EDIT:
In response to your comments, try this version to deal with longs:
long arrayToLong(int[] arr)
{
StringBuilder s = new StringBuilder();
for (int i : arr)
{
s.append(i);
}
return Long.parseLong(s.toString());
}
Edit 2:
In response to your second comment:
int[] longToIntArray(long l)
{
String s = String.valueOf(l); //expand number into a string
String token;
int[] result = new int[s.length() / 2];
for (int n = 0; n < s.length()/2; n ++) //loop through and split the string
{
token = s.substring(n*2, (n+2)*2);
result[n] = Integer.parseInt(token); //fill the array with the numbers we parse from the sections
}
return result;
}
yeah you can write the function yourself
int toInt(int[] array) {
int result = 0;
int offset = 1;
for(int i = array.length - 1; i >= 0; i--) {
result += array[i]*offset;
offset *= 10;
}
return result;
}
I think the logic behind it is pretty straight forward. You just run through the array (last element first), and multiply the number with the right power of 10 "to put the number at the right spot". At the end you get the number returned.
int nbr = 0;
for(int i = 0; i < ar.length;i++)
nbr = nbr*10+ar[i];
In the end, you end up with the nbr you want.
For the new array you gave us, try this one. I don't see a way around using some form of String and you are going to have to use a long, not an int.
int [] ar = {2, 15, 14, 10, 15, 21, 18};
long nbr = 0;
double multiplier = 1;
for(int i = ar.length-1; i >=0 ;i--) {
nbr += ar[i] * multiplier;
multiplier = Math.pow(10, String.valueOf(nbr).length());
}
If you really really wanted to avoid String (don't know why), I guess you could use
multiplier = Math.pow(10,(int)(Math.log10(nbr)+1));
which works as long as the last element in the array is not 0.
Use this method, using a long as your input is to large for an int.
long r = 0;
for(int i = 0; i < arr.length; i++)
{
int offset = 10;
if(arr[i] >= 10)
offset = 100;
r = r*offset;
r += arr[i];
}
This checks if the current int is larger than 10 to reset the offset to 100 to get the extra places required. If you include values > 100 you will also need to add extra offset.
Putting this at end of my post due to all the downvotes of Strings...which is a perfectly legitimate answer...OP never asked for the most efficient way to do it just wannted an answer
Loop your array appending to a String each int in the array and then parse the string back to an int
String s = "";
for(int i = 0; i < arr.length; i++)
s += "" + arr[i];
int result = Integer.parseInt(s);
From your comment the number you have is too long for an int, you need to use a long
String s = "";
for(int i = 0; i < arr.length; i++)
s += "" + arr[i];
long result = Long.parseLong(s);
If you can use Java 1.8, stream API makes it very simple:
#Test
public void arrayToNumber() {
int[] array = new int[]{1,2,3,4,5,6};
StringBuilder sb = new StringBuilder();
Arrays.stream(array).forEach(element -> sb.append(element));
assertThat(sb.toString()).isEqualTo("123456");
}
you can do it that way
public static int[] plusOne(int[] digits) {
StringBuilder num= new StringBuilder();
PrimitiveIterator.OfInt primitiveIterator = Arrays.stream(digits)
.iterator();
while (primitiveIterator.hasNext()) {
num.append(primitiveIterator.nextInt());
}
int plusOne=Integer.parseInt(String.valueOf(num))+1;
return Integer.toString(plusOne).chars().map(c -> c-'0').toArray();
}
BE SIMPLE!!!
public static int convertToInteger(int... arr) {
return Integer.parseInt(Arrays.stream(arr)
.mapToObj(String::valueOf)
.collect(Collectors.joining()));
}
this also possible to convert an Integer array to an int array
int[] result = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
result[i] = arr[i].intValue();
}

How can I allocate memory for an array of digits (int) of a number with the length being equal to the number of digits of that number?

e.g. for int n = 1234 I could create a string (s.valueOf(n)), then I would define the array like this:
int[] array = new int[s.length()]; //this allocates memory for an array with 4 elements
Is there any other way to do this without using a string and only integers?
You can use Math#log10 to find the number of digits.
numOfDigits = (int)(Math.log10(n)+1);
Now you do:
int[] array = new int[numOfDigits];
Note that if n = 1999, numOfDigits will be 4. So you're allocating a memory for 4 integers and not 1999 integers.
But be careful, while reading the documentation of the method, you'll note:
If the argument is positive zero or negative zero, then the result is
negative infinity.
I assume you are talking about Java, so:
int value = myValue;
for (int noOfDigits = 1; Math.abs(value) >= 1; ++noOfDigits) {
value /= 10;
}
int[] array = new int[noOfDigits];
This does not include space for the leading sign if the number is negative, but you can easily test this condition and increment noOfDigits by one.
Use log function to find the no. of digits.
int size = (int)Math.log10(1234)+1;
int[] array = new int[size];
According to my understanding you can do the following to get count of digits
int n = 12345;
int count = 1;
while(n>10){
n = n/10;
count++;
}
int[] array = new int[count];
if (n>0){
numberOfDigets = (int)(Math.log10(n)+1);
}
else if (n < 0){
numberOfDigets = (int)(Math.log10(Math.abs(n))+1);
} else {
numberOfDigets = 1;
}
If n is bigger then zero use the Math.log10 function as Maroun Maroun wrote. If the n is less the zero use the Math.abs function to get a positiv value. If you want to allocate space for the - the add 2 instead of 1. The else clause is for the case when n is zero and sets numberOfDigets to 1.
If an extra call to a java function don't matter use this code.
if (n != 0){
numberOfDigets = (int)(Math.log10(Math.abs(n))+1);
} else {
numberOfDigets = 1;
}
Math.abs(n) will always return a positiv version of n. The value to watch out for is the Integer.min_value beacuse that value will still be negativ, but that is another question.

Improving performance of addition with very big numbers

I wrote this program to calculate very big numbers without using any BigInteger method. I finished it and it's working properly. I used StringBuilder and lots of parseInt call to get it done. Is there a more efficient way to do this?
By the way, this is just worksheet, ignore bad programming style, after finishing my job, I will reorganize that.
private String add (String x, String y)
{
String g = "";
StringBuilder str = new StringBuilder();
int sum;
double atHand = 0;
int dif = (int)(Math.abs(x.length()-y.length()));
if(x.length() >= y.length()) //adding zero for equalise number of digits.
{
for(int i = 0; i<dif; i++)
g += "0";
y = g+y;
}
else
{
for(int i = 0; i<dif; i++)
g += "0";
x = g + x;
}
for (int i = y.length()-1; i >=0 ; i--)
{
sum = Integer.parseInt(x.substring(i, i+1)) +Integer.parseInt(y.substring(i,i+1)) + (int)atHand;
if(sum<10)
{
str.insert(0, Integer.toString(sum));
atHand = 0;
}else
{
if(i==0)
str.insert(0, Integer.toString(sum));
else
{
atHand = sum *0.1;
sum = sum %10;
str.insert(0, Integer.toString(sum));
}
}
}
return str.toString();
}
Instead of doing it character by character, you should take k chars at a time, such that it can fit into a Java int or long. use some predetermined threshold that can hold both the "block", and depending on implementation, any overflow (i.e. such that (threshold * 2) < positive_type_limit). To make things easier, use a threshold that is a power of ten, so you can directly map it to characters in a string-representation of a base 10 number (e.g. if your overflow threshold is one million, then you can take 6 characters at a time) - this also have the added benefit that you can efficiently convert it back to a string.
Then your "blocks" are much bigger. you would then add and do overflow using these blocks and your limit/threshold (which is based on what integer primitive type you use). So basically you are operating on an array of ints.
You will still have time complexity of O(n), but it will be a smaller n (more specifically, it will be O(n/k) where k is the number of decimal digits one block represents.)
I believe that all solutions involve splitting the big number into smaller blocks and operating on them. You have already done this, just your current solution is the special case of blocksize=k=1.
To get the most of the block, you might use a power of 2 as the limit e.g. for a 32 bit unsigned integer type, you would set your threshold to 2^31 (or you could set it to 2^32, but it depends on where and how you are storing the overflow to pass over to the next element).
I would not be surprised if BigInteger uses a similar technique.

Categories

Resources