I am trying to print every 3rd character of a string so an example would be:
123456 returns 36
But my code below returns 14
public String getEveryThird() {
String newString = "";
for (int i = 0; i < string.length(); i++) {
if (i % 3 == 0) {
newString += (string.charAt(i));
}
}
return newString;
}
Good try. The only problem is you choose the wrong remainder of the division since elements start from 0.
Try this condition:
if (i % 3 == 2)
Your current approach is off in the remainder (as already mentioned), however a much faster approach is available; instead of iterating every character, start with the third character and increase your index by three on each iteration. Remember, the third character is at index two (0, 1, 2). Also, it is better to use a StringBuilder over String concatenation (as Java String is immutable). Like,
StringBuilder sb = new StringBuilder();
for (int i = 2; i < string.length(); i += 3) {
sb.append(string.charAt(i));
}
return sb.toString();
It is returning 14 because your loop starts in 0 and 0 % 0 is equal to 0.
Then, when it gets to number 4, the index i is equal to 3, and again 3 % 3 = 0.
Try something like:
if((i+1) % 3 == 0){
newString += (string.charAt(i));
}
Related
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.
I want to take in a string for example "1234567890" and add commas to each thousands place in the number. However, I don't want to parse this string into an int or long. I think I might need to use recursion but I dont know how.
String number1 = "1234567890";
System.out.println(stringNumberAddCommas(number1));
//output == 1,234,567,890
public static String stringNumberAddCommas(String number1){ }
we can achieve this as below as well-
public static String stringNumberAddCommas(String number) {
for (int i = number.length() - 1; i >= 0; ) {
if (i >= 3) {
number = number.substring(0, i - 2) + "," + number.substring(i - 2);
}
i = i - 3;
}
System.out.println("number=" + number);
return number;
}
There's no need to mess with recursion; all you need is to realize that you need to either work backwards or do some very basic math based on length.
Given a pile o digits that is, say, 8 characters long, that's all the information you need to know that the first comma is after 2 digits, and then every further comma at +3 digits from that position until you reach the end.
Tools needed:
"12345678".length() (= 8)
"12345678".substring(2, 5) (= "345")
a for (int i = ...; i < in.length(); i+= 3) loop.
a new StringBuilder() along with its .append() method, both for appending the comma as well as those substrings.
Some exceedingly basic math on that length, involving in particular the % operator. a % b divides a by b, tosses the result in the garbage, and returns the leftovers. In other words, 5 % 3 returns 2 (because 5 divides into 3 one time, and that leaves a remainder of 2).
String test = "1234567890";
String reversed = new StringBuffer(test).reverse().toString();
int i = 0;
StringBuilder ans = new StringBuilder();
while(i+3<reversed.length()){
ans.append(reversed, i, i + 3).append(",");
i+=3;
}
ans.append(reversed, i, reversed.length());
String solution = ans.reverse().toString();
I'd define an offset to find the length of the first substring, then iterate over the string in 3 character substrings.
StringJoiner would also be helpful in adding the needed commas.
public static String stringNumberAddCommas(String str){
int offset = str.length() % 3 != 0 ? str.length() % 3 : 3;
StringJoiner sj = new StringJoiner(",");
for (int s = 0, i = offset; i <= str.length(); s = i, i += 3) {
sj.add(str.substring(s, i));
}
return sj.toString();
}
I want to create a loop where when you add a number, it gives you the equivalent character in that position in the alphabet. For example, a = 0, b = 1 etc..
I've already created that and it works, but the problem I have is that when it reaches 26, I would like it go back and continue the loop. For example, 25 is z, so 27 should be b.
Code:
char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toLowerCase().toCharArray();
if (i < 0)
{
return null;
}
if(i > 25)
{
i = 0;
}
return Character.toString(alphabet[i]); //converts character to String and returns the character
}
You can use the modulo operation on i.
char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toLowerCase().toCharArray();
int i =30;
System.out.println(alphabet[i % alphabet.length]);
You don't need any arrays or loops at all. Just do this:
return (char)('a' + (i % 26));
Try using a modulo operator for your indices. For example,
char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toLowerCase().toCharArray();
if (i < 0) return;
i = i % 26;
return Character.toString(alphabet[i]);
Or
char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toLowerCase().toCharArray();
if (i > 0)
return Character.toString(alphabet[i % 26]);
else
return;
I write the following code that will read a line, convert them into integer and count how many even, odd, and zero digits in a line.
But the problem is that, whenever I enter zero, it will make calculation on the countEven in my code, rather than countZero.
What's wrong with my code?
I don't have any problem on count even digits and odd digits in my code, it's just zeros.
Scanner stdin = new Scanner(System.in);
String str = "";
int countOdd = 0, countEven = 0, countZero = 0;
str = stdin.nextLine();
char[] breakDown = str.toCharArray();
Integer convertInt;
for (int i = 0; i < breakDown.length; i++) {
convertInt = new Integer(breakDown[i]);
if (convertInt % 2 == 1)
countOdd++;
if (convertInt % 2 == 0 && convertInt != 0)
countEven++;
if (convertInt == 0)
countZero++; }
When you cast the character '0' to an integer, it becomes 48, not 0. The expression breakDown[i] is of type char, but it is getting cast to int when you pass it to the Integer constructor.
You could just get rid of the conversion to Integer and write this inside your loop.
if (breakDown[i] % 2 == 1) {
countOdd++;
}
if (breakDown[i] % 2 == 0 && breakDown[i] != '0') {
countEven++;
}
if (breakDown[i] == '0') {
countZero++;
}
The Problem you have in your code is that new Integer(breakDown[i]) returns the value of the ASCII code and not the actual value of the digit. So it return 0x30, this is even and your code correctly increases countEven and not countZero.
First solution in my mind, use Integer.valueOf(breakDown[i]-0x30) instead.
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();
}