How to sum consecutive equal digits in a number in Java - java

The following question was asked in my last interview (yesterday), and I'm trying to solve it since then (couldn't solve it in the interview).
Sorry for any grammar mistakes or any logical mistakes, I don't have the question, it was written by memory:
You are given a number in a string format, for example: "14438832066".
You got to sum up the consecutive equal digits in that number. If no
consecutive equal digit was found, just add the digit to the result.
for example: solution(19938832066) => 11831632012
Explanation: first digit is 1.
The second and third digits are both 9 which means they will turn into 18 in the result string.
So on
with the rest of the digits (as you can see, the last 2 digits are both 6 which means they will turn into 12 in the result string).
You are required to do that for the result string as well, if needed, until no equal consecutive digits are found in the number.
Example:: number: 14438832066 solution( "19938832066") ->"11831632012" -> "2831632012"
Explanation: first result is 11831632012, but then you can see that there are still equal consecutive digits : the first and the
second digits are both 1. So process that number as well.
You are given a string and must return a string.
My solution:
I couldn't write the solution, I don't know why. It's a pretty simple question, I thought going recursive at first but didn't want to complex things.
I wrote 2 helper methods:
one that returns a boolean whether the number consists of equal consecutive digits.
one that actually makes the business logic:
turn the string into a char array
create a counter that will count instances of the same digit - (int counter = 1).
loop on the array from the first to the one before the last element :
inside the loop:
//equal digit was found - increment counter and continue to next digit
if char[i] == char[i+1] then counter++
//calculation in case we are done counting the same digit
else if counter > 0 then result.append(counter*digit[i])
// if no consecutive equal digit was found
else result.append(digit[i])
end loop: return result
Problems I had:
I created the counter inside the loop, so each iteration it got rested. took me few minutes to realize.
I had troubles realizing that 'int(digit[i])' doesn't give me the numeric value of the char, it gives the ASCII value. I had to use "Character.getNumericValue" (don't remember the exact name of the method).
Because of these problems, it took me 45 minutes to write the solution which in the end didn't even work.
I'll be glad to get a working solution, and even better - to get any feedback and tips on my solution and what, in your opinion, were my mistakes.
Thank you.

Your pseudo-code seems alright, as far as it goes. What's missing is that you don't repeatedly check the result string to see if another pass is required. I also show how you don't need to remember the API to convert a character to a digit; if you know the digits are decimal, you can interpret them yourself. As an interviewer, I would accept that there is an API that you can't precisely remember or your home-brew solution as equally valid.
String transform(String number) {
while (true) {
String result = collapse(number);
if (result.equals(number)) return result;
number = result;
}
}
private static String collapse(String number) {
StringBuilder result = new StringBuilder();
for (idx = 0; idx < number.length(); ) {
int mark = idx;
int digit = digitAt(number, idx++);
while (idx < number.length() && digitAt(number, idx) == digit) ++idx;
result.append((idx - mark) * digit);
}
return result.toString();
}
private static int digitAt(String num, int index) {
char ch = number.charAt(index);
if (ch < '0' || ch > '9') throw new IllegalArgumentException();
return ch - '0';
}
The preceding is a naïve approach that transforms the string until there are no changes. I suspect there might be a more "elegant" approach that works from left to right through the input in a single pass, but it would take some thought, and I probably couldn't come up with that in an interview.

Here's an algorithm that uses recursion and a for-loop to add consecutive equal digits. I think the code is pretty self-explanatory but please ask if you have any queries.
public static String addConsecutiveDigits(String number) {
char[] arr = number.toCharArray();
StringBuilder result = new StringBuilder();
boolean foundConsecutive = false; // boolean flag for checking if the number contained consecutive equal digits
for (int i = 0; i < arr.length; i++) {
int digit = arr[i] - '0'; //Subtracting ascii values to get integer values
int newNumber = digit;
if (i != arr.length - 1) {
int nextDigit = arr[i + 1] - '0';
if (digit == nextDigit) { // check if the digits are consecutive digits
newNumber = digit + nextDigit;
i++; // increment i as we have already added the i+1 digit
foundConsecutive = true;
}
}
result.append(newNumber);
}
if (!foundConsecutive) // if no consecutive equal digits were found then return the result;
return result.toString();
else // recurse to check for more consecutive equal digits
return addConsecutiveDigits(result.toString());
}

I'm not a Java guy, so this code might not be ideal but I would do something like this:
public String solve(String input)
{
String result = "";
int i = 0;
while (i < input.length())
{
var first = input.charAt(i);
if (i == input.length() - 1){
result += first;
break;
}
var second = input.charAt(i + 1);
if (first == second){
result += (Character.getNumericValue(first) + Character.getNumericValue(second));
i += 2;
} else {
result += first;
i += 1;
}
}
return result;
}
For the second part, I would just run the function in a loop until the result matches the input.

Related

Find repeating bit sequence in number

How can I find multiples of a given bit sequence?
So the code should work like this:
int bit = 0b100
for (int i = 0; i<=50;i++){
if (bit in i){
print(i);
}
}
This should print 4 (100) and 36 (100100).
I was trying to iterate through it and bit-mask it but it also printed numbers like 40 (101000).
So it should only print numbers containing only multiplies of that sequence (100, 100100, 100100100 ...) but not numbers like 1100, 1001001 ...
You can use the modulo operator and shift operator to check the lower bits of the number and "reduce" the incoming number to check the next lower bits of the remaining number. The algorithm works like this:
Do a modulo of the sequence on the number to check. The modulo must be 0.
So when you have the sequence 0b100 and you have a number to check like 0bXXXXXXXX101 the modulo would be 0b001, which is not 0 and you know the number can't be a sequence of multiple 0b100s.
Shift the remaining number to the right, since you have already checked the first N bits on the right.
You shift the number with the >> operator. This will move the bits to the right, dropping the already checked bits:
0bXXXXXXXX101
0bXXXXXXXX (shifted to the right)
The tricky part is to calculate how big the shift is. You can use log2() to figure that out. When you completed the shift, you go back to point 1 above.
The complete code can look like this:
public static boolean isMultipleOfSequence(int sequence, int number) {
if (sequence == 0) {
return number == 0;
}
while (number != 0) {
int remaining = number % sequence;
if (remaining != 0) {
return false;
}
int shift = log2(sequence);
number = number >> shift;
}
return true;
}
public static int log2(int value) {
return Integer.SIZE-Integer.numberOfLeadingZeros(value);
}
When you try it with the following code:
System.out.println(isMultipleOfSequence(0b100, 0b100));
System.out.println(isMultipleOfSequence(0b100, 0b100100));
System.out.println(isMultipleOfSequence(0b100, 0b100100100));
System.out.println(isMultipleOfSequence(0b100, 0b101100100));
System.out.println(isMultipleOfSequence(0b100, 0b100110100));
System.out.println(isMultipleOfSequence(0b101, 0b101101101));
System.out.println(isMultipleOfSequence(0b101, 0b100101101));
You will get the following output:
true
true
true
false
false
true
false
You might need to check for negative inputs as this method only works for positive numbers.
I'm not sure how to do it with pure math, but regex works:
Pattern pattern = Pattern.compile("^(100)+$");
for (int i = 0; i < 100; i++) {
String binary = Integer.toBinaryString(i);
if (pattern.matcher(binary).find()) {
System.out.println(i + " " + binary);
}
}
Edit: What about going the other direction?
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 10; i++) {
builder.append("100");
System.out.println(Integer.parseInt(builder.toString(), 2));
}

Addition of two given numbers

Basically is about the binary numbers, the user needs to input two random numbers, both numbers will be added, and the addition of those two numbers only needs to have ones and zeros for example 5+6==11 OR 55+55=110, then throw a message saying “the addition only has 1’s and 0’s, otherwise for example 25+46=71 or 575+575=1150 then a message saying the addition does not have only 1’s and 0’s.
I just started learning java and i can’t find anything helpful for this problem, i already know the conditionals if only have ones and zeros or not.
this is the code i already have, but when i input for example 575+575+1150 says only has 1's and 0's, i guess i cant use .contains for this.
public static void main(String[] args) {
Scanner read = new Scanner(System.in);
int n1;
int n2;
int add;
System.out.print("Input Number 1: ");
n1=read.nextInt();
System.out.print("Input number 2: ");
n2=read.nextInt();
System.out.println();
add=n1+n2;
System.out.println("The addition is = "+add);
String S = String.valueOf(add);
if(S.contains("1") && S.contains("0")) {
System.out.print("The addition only has 1's and 0's");
}
else{System.out.print("The addition does not only have 1's and 0's");}
}
}
I saw your code and and the resultant sum 1150 does contain 1's and 0's.
s.contains(x);
This function only checks if the string contains the value x or not. Since "1150" contains both 1's and 0's therefore your function prints the wrong output.
One way of solving this problem would be to add the two numbers and then check the resultant sum digit by digit. You can make a function that will do that for you.
public void checkOnesAndZeros(int resultantSum) {
while (resultantSum > 0) {
int remainder = resultantSum % 10;
if(remainder != 1 && remainder != 0) {
System.out.println("The addition does not have only 1’s and 0’s.");
return;
}
resultantSum = resultantSum / 10;
}
System.out.println("The addition only has 1’s and 0’s");
}
One way is to create a String using the added numbers and iterating through the characters.
public static boolean isResultBinary(int n1, int n2) {
String sum = n1 + n2 + "";
for (int i = 0; i < sum.length(); i++) {
char c = sum.charAt(i);
if (c != '1' && c != '0') return false;
}
return true;
}
Here's a method I wrote, it checks every character c to see if it is either '0' and '1'. If a character is not either one, the method will return false. Otherwise, it'll loop through the whole string and return true.
To get your desired output, use this method like this in within your main method:
if (isResultBinary(n1, n2)) System.out.println("The addition only has 1's and 0's");
else System.out.print("The addition does not only have 1's and 0's");
Here is another take on the question.
convert the sum to a string and then try and parse it as binary.
if it isn't binary, an exception will be thrown, so return false.
otherwise return true.
int[] sums = { 110, 120, 10111, 250, 203, 2011, 1110111 };
for (int n : sums) {
System.out.printf("%8s - %s%n", n,
"is " + (checkOnesAndZeros(n) ? "" : "not ")
+ "all ones and zeros");
}
prints
110 - is all ones and zeros
120 - is not all ones and zeros
10111 - is all ones and zeros
250 - is not all ones and zeros
203 - is not all ones and zeros
2011 - is not all ones and zeros
1110111 - is all ones and zeros
The method
public static boolean checkOnesAndZeros(int resultantSum) {
try {
Integer.parseInt(Integer.toString(resultantSum), 2);
return true;
} catch (NumberFormatException nfe) {
return false;
}
}

Converting a decimal number to binary in java not showing leading zeroes

This is my function in Java:
public static String convertFromDecimal(int number, int base)
{
String result = "";
/*
* This while loop will keep running until 'number' is not 0
*/
while(number != 0)
{
result = (number%base) + result; // Appending the remainder
number = number / base; // Dividing the number by the base so we can get the next remainder
}
// If the number is already 0, then the while loop will ignore it, so we will return "0"
if(result == "")
{
return "0";
}
return result;
}
It works fine for numbers that convert to numbers not beginning with 0, if the number is supposed to have a zero at the start, it will not record it, could anyone tell me why?
For example, if I print out
convertFromDecimal(13,2) it returns
1101
Which is correct, but if I print out
convertFromDecimal(461,2), I get
111001101
Where the actual answer is
0000000111001101
So it's the same as my answer without the leading zeroes, if anyone knows why I would appreciate the help, thank you.
EDIT My question is different because I don't want 16 digits, I want the binary number of the given decimal, a calculator like this can explain what I want.
I assume you are looking to format all your answers as shorts (16 bits).
In this case, simply check the length of your current string, and add on zeroes as needed.
int zeroesRemaining = 16 - result.length();
for (int i = 0; i < zeroesRemaining; i++) {
result = "0" + result;
}
Alternatively, if you want to do it faster, use a StringBuilder.
int zeroesRemaining = 16 - result.length();
StringBuilder tempBuilder = new StringBuilder(result);
for (int i = 0; i < zeroesRemaining; i++) {
tempBuilder.insert(0, 0); //inserts the integer 0 at position 0 of the stringbuilder
}
return tempBuilder.toString(); //converts to string format
There is also probably a formatter that could do this, but I don't know of such.
If you want to change the number of zeroes to be the closest integer primitive, just set zeroesRemaining to be the (least power of 2 that is greater than the number of bits) minus (the number of bits).
Since you want fixed lengths for your result, in groups of 8 bits, the easiest way is to append 0 to the front of your result until its length is a multiple of 8.
That is as simple as
wile (result.length() % 8 > 0)
{
result = "0" + result;
}
return result;

Magic Number - The Quest for the Simplest

Is there any better logic that can be applied to magic numbers?
Or is there a magic number that I am missing out on?
Please help me out with this simplest working code!
A Magic number is a number whose sum of digits eventually leads to 1.
Example#1: 19 ; 1+9 =10 ; 1+0 = 1. Hence a magic number.
Example#2: 226; 2+2+6=10; 1+0 =1. Hence a magic number.
Example#3: 874; 8+7+4=19; 1+9=10; 1+0=1. Hence a magic number.
boolean isMagic ( int n ) {
return n % 9 == 1;
}
Well, I'm not 100% that the code you placed would work to get a "magic number", but my approach to the problem would be different.
First, I'd receive a String, so that I can get the different digits of the number with a String.charat.
Then I'd use a while cycle to sum the numbers until it gets a single digit number, then check if it's 1.
The code would be
boolean isMagicNumber(String number) {
int[] digits = new int[number.length()];
int sum = 99;
while(sum/10 >= 1) {
sum = 0;
for(int i = 0; i < number.length(); i++) {
sum += Integer.parseInt(""+number.charAt(i));
}
if(sum == 1) {
return true;
}
}
return false;
}
There might be a better solution, but this is what I'd do to solve the problem.

How does this code add commas before every three digits?

Help me to understand how this code works. It essentially adds commas into a string of numbers. So if the user types a 1 to 3 digit number it is unchanged. For a four digit number ,it adds a comma so
1111 becomes 1,111
11111 becomes 11,111
111111111 becomes 11,111,111
and so on. Here's the code:
private String addCommasToNumericString (String digits)
{
String result = "";
int len = digits.length();
int nDigits = 0;
for (int i = len - 1; i >= 0; i--)
{
result = digits.charAt(i) + result;
nDigits++;
if (((nDigits % 3) == 0) && (i > 0))
{
result = "," + result;
}
}
return (result);
}
I´ll explain what I do understand of it
The for loop basically counts the length of the number the user has written to avoid putting a comma before the first number (e.g. ,1111). And while i is less than the length of the string it subtracts 1.
result returns the char at position i, since it counts downwards it returns the chars "opposite" from right towards left.
nDigits adds 1 from to the initial value of 0 on each iteration through the loop.
I guess now is where I am having trouble seeing exactly what is going on: if ("nDigits % 3) == 0.
So for the two first iteration through loop it will not execute the if loop because:
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
nDigits starts out as 1 because of the nDigits++ code inside the for loop, so how does it put the comma after three digits and not two? And how does it know when there is only 4 or 5 digits to place the comma corretly at position 1 and two (1,111 - 11,111)?
I think the easiest way to explain this is to slow it down to each pass.
The loop starts at the end of the string so if you have the string 12345, then after the first time through the loop result will be "5" and nDigits will be 1.
The next time through, '4' will be added to the front of the result giving you "45" and nDigits will be 2.
The third time through, it adds '3' to the front of result making that "345" and then the if-then triggers and adds a comma to the front. Result is now ",345".
More passes will give you "12,345".
I think what is confusing you is that loop starts at the '5' and not at the '1'. Everything is added to the front of result and not to the end as you would normally expect.
Hope this helps!
The key thing in this method is to count the digits from right to left. If you don't do it that way it won't work.
You can also do the same with String Manipulation instead of char manipulation. Maybe it makes it easier to understand so I'll provide an example.
My solution involves the use of the subString Method and operates in a similar manner to yours. Starting FROM RIGHT TO LEFT, it divides the original String in two substrings and adds a comma in between them every time there is a 3 digits group.
private String addCommas (String digits) {
String result = digits;
if (digits.length() <= 3) return digits; // If the original value has 3 digits or less it returns that value
for (int i = 0; i < (digits.length() – 1) / 3; i++) {
int commaPos = digits.length() – 3 – (3 * i); // comma position in each cicle
result = result.substring(0, commaPos) + "," + result.substring(commaPos);
}
return result;
}
The variable result is used for incremental build of the final output, in each iteration one or two chars are concatenated from left (i.e. the string is build from right to left).
One char is concatenated everytime by running
result = digits.charAt(i) + result;
it is the actual digit
the second char is concatenated in each third iteration by running
result = "," + result;
it is the order separator
The implementation is not optimal at all, because in Java the string are immutable and result = "," + result; ends up in creating a new object. The StringBuffer or StringBuilder are far more effective for this purpose.
Essentially what this does is start at the last digit of the number and iterate through from right to left, prepending them to the result String and putting a comma in every 3 characters.
In this particular code, len holds the total length of the number and nDigits is a count of how many of those digits have been evaluated already. Starting at position len-1 (so the index of the last digit of the number), the for-loop iterates through position 0 (the first digit of the number). It takes the digit at position i, puts it at the front of the result String, and then evaluates if there should be a comma in front of it. nDigits % 3 will return 0 every 3rd digit, so the if statement evaluates if there should be a comma by checking that if there have been 3 digits written and the one you just wrote was not 0.
for (int i = len - 1; i >= 0; i--)
i starts with len - 1, to start from the last digit. i > 0 in if (((nDigits % 3) == 0) && (i > 0)) is the one that avoid a comma before the first number (e.g. ,1111).
I modified answer of #Antonio Ricardo Diegues Silva for my purposes.
/**
* Get number in {#link String} with divider after 'n' number of digits
* #param number number for processing
* #param n amount after which will be inserted divider
* #return {#link String} number with dividers
*/
public static <T extends Number> String insertDividerBetweenEveryNDigits(T number, int n, String divider) {
StringBuilder builder = new StringBuilder().append(number);
int digitsNumber = builder.length();
if (digitsNumber > n) { // If the original value has n digits or less it just returns that value
for (int i = 1; i <= (digitsNumber - 1) / n; i++) {
int dividerPos = digitsNumber - (n * i); // divider position in each cycle
builder.insert(dividerPos, divider);
}
}
return builder.toString();
}

Categories