How to calculate the consecutive sum of number in a string? - java

I would like to find the sum of integer in string. For example:
String myString= "The price is 345and the tax1 is 12sales";
String output = "The price is 12and the tax1 is 3sales";
I found few approaches none is displaying the final output the way I need.
int sum = 0;
for (int I =0; i < myString.lengh(); i++)
{
char c = myString.charAt(i);
if(Character.isDigit(c))
{
int value = Integer.parseInt(String.valueOf(c));
}
}
I am getting the total sum but I would like to be able to append the string with individual sums.
output = "The price is 12and the tax1 is 3sales"

I'm using a StringBuilder for building the result string. You have to keep adding the digits as long as you encounter digits. When you encounter a character, you have to append the sum at hand (if you have) and then append the character.
Note: This won't work if the sum can be 0 (and needs to be tweaked to support that).
int sum = 0;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < myString.length(); i++)
{
char c = myString.charAt(i);
if(Character.isDigit(c))
{
sum += Integer.parseInt(String.valueOf(c));
} else {
if (sum != 0) {
builder.append(sum);
}
builder.append(c);
sum = 0; //reset
}
}

add an if statement checking the next character for a digit, if it's a digit add it, otherwise you are done and can print it.
However, your input is quite unusual, are you sure you can not improve the input itself?

Related

How to delete specific digit from integer?

In the n integer where n = 1237534 (for example) I have to delete digit 3 so I can get the biggest value possible. n can be negative number also.
I can get 127534 or 123754.
The bigger is of course 127534, but how can I return it?
I've tried something like this:
int n = 1237534;
String newNum = String.valueOf(n);
int[] newGuess = new int[newNum.length()];
for (int i = 0; i < newNum.length(); i++) {
newGuess[i] = newNum.charAt(i) - '0';
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < newGuess.length; i++) {
if (!(newGuess[i] % 3 == 0)) {
sb.append(newGuess[i]);
}
}
System.out.println(sb);
I get 12754 which is not correct answer. Anyone maybe have an idea how to solve it?
This does not require arrays nor loops:
int n = 1237534;
String newNum = String.valueOf(n);
char c = '3';
StringBuilder sb1 = new StringBuilder( newNum );
StringBuilder sb2 = new StringBuilder( newNum );
int newGuess1 = Integer.parseInt(sb1.deleteCharAt(newNum.indexOf(c)).toString());
int newGuess2 = Integer.parseInt(sb2.deleteCharAt(newNum.indexOf(c, newNum.indexOf(c)+1)).toString());
System.out.println( newGuess1 > newGuess2 ? newGuess1: newGuess2 );
Here is an alternative approach that also checks to ensure that the number actually contains the digit. Otherwise, an exception could be thrown if the index returns -1.
The method simply deletes the first or last occurrence of the digit depending on whether the number is negative or not.
int n = 1234321;
int bad_digit = 3;
StringBuilder sb = new StringBuilder(Integer.toString(n));
String bad = Integer.toString(bad_digit);
int idxOfFirst = sb.indexOf(bad);
// first, make certain the number contains the digit.
if (idxOfFirst >= 0) {
if (sb.charAt(0) == '-') {
// if negative, delete last character to give the larger value
sb.deleteCharAt(sb.lastIndexOf(bad));
} else {
// else delete the first character to give the larger value
sb.deleteCharAt(idxOfFirst);
}
}
System.out.println(sb);
This prints the string rather than convert to an integer since printing an integer results in conversion to a string anyway. If the digit does not appear in the original number, then the original is printed. You can alter that handling to meet your requirements.
How about this:
int n = 123454321;
int bad_digit = 3;
StringBuilder s = new StringBuilder(n + "");
s.reverse();
System.out.println("Reversed String: " + s);
for (int i = 0; i < s.length(); i++) {
// Check if the character at index 'i' and the
// digit are equal, by converting both to strings
if (("" + s.charAt(i)).equals("" + bad_digit)) {
s.replace(i, i + 1, "");
break;
}
}
System.out.println("Reversed String after removing the digit (if found): " + s);
s.reverse();
System.out.println("Greatest number without the bad digit: " + s);
Basically, we need to remove the last occurrence of the digit to be removed (the bad_digit). So we convert the number to a string and reverse it. Now we need to remove the first occurrence of the digit. So we iterate over the characters, and when we find that digit, we remove it from the string, and exit the loop. Now we reverse the string again, and the output is what you want.

credit card numbers need to be added without the dash

So one of the conditions for the credit card number to be valid is that "the sum of first 4 digits must be 1 less than the sum of the last 4 digits" I believe the problem could be it's counting the dashes as a digit but not sure. the rule 4 is that the sum of all digits must be divisible by 4, which seems to work, but rule 5 doesn't.
int sum = ccNumber.chars().filter(Character::isDigit).map(Character::getNumericValue).sum();
if(sum%4!=0){
valid = false;
errorCode = 4;
return;
}
// set values and for loop for fifth rule.
String digits = ccNumber.replaceAll("[ˆ0-9]","");
int firstfourdigits = 0;
int lastfourdigits = 0;
for(int i=0; i<4; i++)
firstfourdigits = firstfourdigits + Character.getNumericValue(ccNumber.charAt(i));
for (int i=0, m = ccNumber.length()-1; i<4; i++, m--)
lastfourdigits = lastfourdigits + Character.getNumericValue(ccNumber.charAt(m));
// mutator for fifth rule
if(lastfourdigits!= firstfourdigits -1){
valid = false;
errorCode = 5;
return;
}
sorry I'm lost and new to coding.
Edit since you altered your question. Original anwser to the original question is at the bottom part
Checking if first part and last part have a difference of one
The code you currently have is close, but there are some mistakes here and there.
Filtering out only digits: The code you use to filter out all characters that are not numeric should work, but in your following code you are no longer using this filtered value in your loop.
firstfourdigits + Character.getNumericValue(ccNumber.charAt(i));
This should use the variable with only your numeric values => digits
firstfourdigits = firstfourdigits + Character.getNumericValue(digits.charAt(i));
Difference in first group vs last group: The -1 should be replaced by +1 here. When you are experiencing problems with this type of checks, it's always adviced to try and calculate it on a piece of paper. Lets assume the sum of the first 4 digits is 8 and the sum of the last 4 digits is 9. As per the requirement, this is a valid number, and should result to false in your check if(lastfourdigits!= firstfourdigits -1)
Let's fill it in: 9 != 8-1 => 9 != 7 so this returns false, and marks it as invalid. If we base it on the requirement, you could write the sum of the first 4 digits should be one less then the last 4 digits as: firstfourdigits = lastfourdigits - 1. This is mathmatically the same as lastfourdigits = firstfourdigits + 1. However, in our check we want to know if this check is not correct, so we should change the statement to: if(lastfourdigits != firstfourdigits + 1)
These 2 changes should give you the results you asked for. Combining these changes, we come to the following code example
String digits = ccNumber.replaceAll("[ˆ0-9]", "");
int firstfourdigits = 0;
int lastfourdigits = 0;
for (int i = 0; i < 4; i++)
firstfourdigits = firstfourdigits + Character.getNumericValue(digits.charAt(i));
for (int i = 0, m = ccNumber.length() - 1; i < 4; i++, m--)
lastfourdigits = lastfourdigits + Character.getNumericValue(digits.charAt(m));
if(lastfourdigits!= firstfourdigits + 1){
valid = false;
errorCode = 5;
return;
}
Other recommendations
The above example should work for what you asked, and is based on your code. However there are some optimalisations possible to the code to make everything more readable
Use brackets on your for loop: To make it clearer what is inside the for loop, and what isn't, I would advise you to make use of curly brackets. Though they are not required, they will make it very clear what is and isn't in the for loop and will prevent hard to spot issues when you add something extra in the for loop
Use the short notation for addition: Instead of writing firstfourdigits = firstfourdigits + Character.getNumericValue(digits.charAt(i));, You could use a shorter notation of +=. This will take the value on the left side of your equals, and will calculate the sum of that value on the right side. firstfourdigits += Character.getNumericValue(digits.charAt(i));
The code looks like this then:
String digits = ccNumber.replaceAll("[ˆ0-9]", "");
int firstfourdigits = 0;
int lastfourdigits = 0;
for (int i = 0; i < 4; i++){
firstfourdigits += Character.getNumericValue(digits.charAt(i));
}
for (int i = 0, m = ccNumber.length() - 1; i < 4; i++, m--) {
lastfourdigits += Character.getNumericValue(digits.charAt(m));
}
if(lastfourdigits!= firstfourdigits + 1){
valid = false;
errorCode = 5;
return;
}
Anwser to original question to calculate the sum of all digits
You could make use of Character.isDigit(char). To simplify the for loop, you can even make use of a stream to get the sum
int sum = ccNumber.chars().filter(Character::isDigit).map(Character::getNumericValue).sum();
if (sum % 4 != 0) {
valid = false;
errorCode = 4;
return;
}
.chars(): This will create a stream of all the characters in the provided string so that we can loop over them one by one
.filter(Character::isDigit): This will filter out every character that is not a digit
.map(Character::getNumericValue): This will map the stream from Characters to their numeric values so that we can use those further
sum() will calculate the sum of the numeric values that we currently have in the Stream
The difference is always a positive value e.g. the difference between 4 and 5 or between 5 and 4 is the same i.e. 1. In other words, you need to compare the absolute value of the subtraction with 1.
Therefore, replace
if(lastfourdigits!= firstfourdigits -1)
with
if(Math.abs(lastfourdigits - firstfourdigits) != 1)
Another mistake in your code is that you have used ccNumber, instead of digits in your loops.
Some recommendations to make your code easier to understand:
Replace for (int i=0, m = digits.length()-1; i<4; i++, m--) with for (int m = digits.length() - 1; m >= digits.length() - 4; m--). Note that I've already replaced ccNumber, with digits in these statements.
Replace ccNumber.replaceAll("[^0-9]","") with ccNumber.replaceAll("\\D", "").
Replace firstfourdigits = firstfourdigits + Character.getNumericValue(digits.charAt(i)) with firstfourdigits += Character.getNumericValue(digits.charAt(i)). Note that I've already replaced ccNumber, with digits in these statements.
Always enclose the body of if and loop statements within { } even if there is just one statement inside the body.
Demo:
public class Main {
public static void main(String[] args) {
System.out.println(isValidOnDiffCriteria("1234-5678-9101-1213"));
System.out.println(isValidOnDiffCriteria("1234-5678-9101-1235"));
System.out.println(isValidOnDiffCriteria("1235-5678-9101-1234"));
}
static boolean isValidOnDiffCriteria(String ccNumber) {
String digits = ccNumber.replaceAll("\\D", "");
int firstfourdigits = 0;
int lastfourdigits = 0;
for (int i = 0; i < 4; i++) {
firstfourdigits += Character.getNumericValue(digits.charAt(i));
}
for (int m = digits.length() - 1; m >= digits.length() - 4; m--) {
lastfourdigits += Character.getNumericValue(digits.charAt(m));
}
if (Math.abs(lastfourdigits - firstfourdigits) != 1) {
return false;
}
return true;
}
}
Output:
false
true
true
Try the code above. Should be what you asked. You don't need a try catch.
static boolean isCardValid(String creditCard) {
// group digits in a string array
String[] cards = creditCard.split("-");
int sumAll = 0;
// for every group of digits we convert it to char[]
for (String card : cards) {
sumAll += sum(card.toCharArray());
}
int firstGroupOfDigits = sum(cards[0].toCharArray()) ;
int lastGroupOfDigits = sum(cards[cards.length-1].toCharArray());
if( firstGroupOfDigits == lastGroupOfDigits -1){
if (sumAll % 4 == 0) {
return true;
}
}
return false;
}
// sum the group of digits separated by "-"
static int sum(char[] chr) {
int sum = 0;
for (char c : chr) {
sum += Character.getNumericValue(c);
}
return sum;
}
Well, your program is not that bad and as far as I can tell there is only one problem and that is the you simply reversed the required test on the first and last groups. I would advise you to ensure the valid is initialized to true as the default. Then if none of the error codes are set, it will return true.
Presently you have the following:
if (lastfourdigits != firstfourdigits - 1) {
valid = false;
errorCode = 5;
}
But what you need is this
if (lastfourdigits != firstfourdigits + 1) {
valid = false;
errorCode = 5;
}
Your also have the following, unnecessary code.
String digits = ccNumber.replaceAll("[ˆ0-9]","");
The reason being is that you are simply using ccNumber starting at the beginning for the first four characters and starting at the end for the last four. In this way you are not encountering dashes so you don't need to get just the digits.
Another recommendation is that as soon as you find an error you set the error code and return immediately. What's the use in continuing to process a card that has already been found to be flawed?
Other considerations and an alterative approach
It may not be a part of the assignment but I would also consider the following:
What if you have more or less than 16 digits?
What if you have more than three dashes giving more than four groups of numbers.
Checking the above would require additional logic and would complicate your effort. But it is something to consider. What follows demonstrates one way to check on those particular format issues and report them. This uses basic techniques and avoids streams so as not to repeat unnecessary operations.
This example throws selective errors based on problems found. Those may be changed or eliminated altogether as explained later. Credit card validation is a task where the most straightforward solution is best and should require low overhead.
First, declare a special exception to catch credit card errors.
class BadCreditCardException extends Exception {
public BadCreditCardException(String message) {
super(message);
}
}
Now declare some test data.
String[] testData = {
"1234-4566-9292-0210",
"1500-4009-2400-1600",
"1500-4009-2400-160000",
"1234-45669292-0210",
"1#34-45-66-9292-0210",
"1234-45B6-9292-0210",
"1234-4566-9292-2234",
"1234-4566-9292-021022",
"1234-4566-9292-0210",
"4567-4566-92!2-6835",
"1234-4566-9292-0210",
"1234-45+6-9292-0210",
"1234-4566-92x2-0210",
"1234-4566-9292-0210",
};
Test the credit cards and report errors. Note that only first encountered errors are reported. There may be multiple errors in the number.
String fmt = "%-23s - %s%n";
for(String card : testData) {
try {
validate(card);
System.out.printf(fmt,card, "Valid");
} catch (BadCreditCardException bce) {
System.out.printf(fmt,card, bce.getMessage());
}
}
The above prints.
1234-4566-9292-0210 - Invalid credit card checksum
1500-4009-2400-1600 - Valid
1500-4009-2400-160000 - Non group of 4 digits
1234-45669292-0210 - Insufficient or too may dashes
1#34-45-66-9292-0210 - Insufficient or too may dashes
1234-45B6-9292-0210 - Non digit found.
1234-4566-9292-2234 - Valid
1234-4566-9292-021022 - Non group of 4 digits
1234-4566-9292-0210 - Invalid credit card checksum
4567-4566-92!2-6835 - Non digit found.
1234-4566-9292-0210 - Invalid credit card checksum
1234-45+6-9292-0210 - Non digit found.
1234-4566-92x2-0210 - Non digit found.
1234-4566-9292-0210 - Invalid credit card checksum
The Explanation
The validate method. The method works as follows.
split the card into groups using the dash (-) as a delimiter.
If there are not four groups, throw an exception.
Otherwise, sum each of the groups as follows each of these is checked during the summation process.
first check that the group is of size four, if not throw an exception.
as the group characters are iterated, if a non-digit is encountered, throw an exception.
otherwise, continue computing the sum for the current group as follows:
If the character is a digit, subtract 0 to convert it to an int
and add to the current sums array element.
when completed, add that group sum to the totalSum of all digits.
if the totalSum is divisible by four and the first group is one less than the last group, it is a valid card. Otherwise, throw an exception.
Alternative error handling modification
If the exceptions are not wanted, but just a pass or fail indication, then make the following changes.
change the void return type to boolean
if an exception was throw, simply return false
if all tests pass, then the last statement should return true
public static void validate(String cardNumber) throws BadCreditCardException {
int [] groupSums = new int[4];
int totalSum = 0;
String [] groups = cardNumber.split("-");
if (groups.length != 4) {
throw new BadCreditCardException("Insufficient or too may dashes");
}
for (int i = 0; i < groupSums.length; i++) {
if (groups[i].length() != 4) {
throw new BadCreditCardException("Non group of 4 digits");
}
for(int digit : groups[i].toCharArray()) {
if (!Character.isDigit(digit)) {
throw new BadCreditCardException("Non digit found.");
}
groupSums[i]+= digit -'0';
}
totalSum += groupSums[i];
}
if (groupSums[0]+1 != groupSums[3] || totalSum % 4 != 0) {
throw new BadCreditCardException("Invalid credit card checksum");
}
}
A separate class for Credit card and its parts
Add a Part class that manages a portion of the credit card
Add a CreditCard class that manages these portions
Valid each portion
In addition to validating each potion individually, validate additional check
Depending on the number of times, the valid & sumDigits method will be called, validation/sum can be added in respective methods or in constructor.
import java.util.Arrays;
public class CreditCard {
private final String input;
private final Part[] parts;
private final boolean valid;
CreditCard(String card) {
this.input = card;
if (card == null || card.length() != 19) {
valid = false;
parts = null;
} else {
parts = Arrays.stream(card.split("-")).map(Part::new).toArray(Part[]::new);
final int totalSum = Arrays.stream(parts).mapToInt(Part::sumDigits).sum();
valid = totalSum % 4 == 0 && parts.length == 4
&& parts[0].sumOfDigits + 1 == parts[3].sumOfDigits
&& Arrays.stream(parts).allMatch(Part::isValid);
}
}
static class Part {
final int num;
final boolean valid;
final int sumOfDigits;
Part(String part) {
int localNum = 0;
try {
localNum = Integer.parseInt(part);
} catch (Throwable ignored) {
}
this.num = localNum;
valid = part.length() == 4 && part.equals(String.format("%04d", num));
if (valid) {
sumOfDigits = part.chars().map(Character::getNumericValue).sum();
} else {
sumOfDigits = -1;
}
}
boolean isValid() {
return valid;
}
int sumDigits() {
return sumOfDigits;
}
}
public static void main(String[] args) {
String[] creditCards = {
"1000-0000-0001-0002",
"0000-0000-0000-0000",
"10000-0000-0001-0002",
"10000000-0001-0002",
"1a00-0000-0001-0002",
"1234-4826-6535-1235",
};
Arrays.stream(creditCards).map(CreditCard::new)
.forEach(c -> System.out.println(c.input + " is " + c.valid));
}
}
Everything is fine except the second for loop and your if condition.
Replace your code with the following changes and it should work fine:
int firstfourdigits = 0, lastfourdigits = 0;
for(int i=0; i<4; i++)
firstfourdigits = firstfourdigits + Character.getNumericValue(ccNumber.charAt(i));
for (int m = ccNumber.length()-1; m>ccNumber.length()-5; m--)
lastfourdigits = lastfourdigits + Character.getNumericValue(ccNumber.charAt(m));
if(firstfourdigits != lastfourdigits - 1){
valid = false;
errorCode = 5;
return;
}
You do not need to extract digits at all.
public boolean ccnCheck(String ccn){
String iccn = ccn.replaceAll("-","");
int length = iccn.length();
int fsum = 0;
int lsum = 0;
int allsum = 0;
for( int i = 0; i < length; i++){
int val = Character.getNumericValue(iccn.charAt(m))
if( i < 4)
fsum += val;
if( i >= length-4)
lsum += val;
allsum += val;
}
if( (allsum % 4) != 0)
return false;
if( fsum != lsum-1 )
return false;
return true;
}
In your rule five check, you're using ccNumber instead of your digits string.
For example, shouldn't
Character.getNumericValue(ccNumber.charAt(i));
be this instead:
Character.getNumericValue(digits.charAt(i));

License Key Formatting code Challenge Leetcode

This is the challenge:
You are given a license key represented as a string S which consists only alphanumeric character and dashes. The string is separated into N+1 groups by N dashes. Given a number K, we would want to reformat the strings such that each group contains exactly K characters, except for the first group which could be shorter than K, but still must contain at least one character. Furthermore, there must be a dash inserted between two groups and all lowercase letters should be converted to uppercase. Given a non-empty string S and a number K, format the string according to the rules described above.
Example 1:
Input: S = "5F3Z-2e-9-w", K = 4 Output: "5F3Z-2E9W" Explanation: The string S has been split into two parts, each part has 4 characters.
Note that the two extra dashes are not needed and can be removed.
Example 2:
Input: S = "2-5g-3-J", K = 2 Output: "2-5G-3J" Explanation: The string S has been split into three parts, each part has 2 characters except the first part as it could be shorter as mentioned above.
Note:
1) The length of string S will not exceed 12,000, and K is a positive integer.2) String S consists only of alphanumerical characters (a-z and/or A-Z and/or 0-9) and dashes(-).
3) String S is non-empty.
Here is my Code:
public static String licenseKeyFormatting(String S, int Key) {
String cleaned = S.replaceAll("[\\-]", "").toUpperCase();
String result = "";
int currentPos = 0;
//IF EVENLY SPLIT
if ( (cleaned.length() % Key) == 0 ) {
int numGroups = cleaned.length()/Key;
for(int i = 0; i < numGroups; i++) {
for (int k =0; k < Key; k++) {
char currentLetter = cleaned.charAt(currentPos++);
result = result + currentLetter;
}
if (i != (numGroups - 1)) {
result = result + "-";
}
}
}
else {
int remainder = cleaned.length() % Key;
for (int i = 0; i < remainder; i++) {
char currentLetter = cleaned.charAt(currentPos++);
result = result + currentLetter;
}
if(remainder == cleaned.length()) {
return result;
}
else {
result = result + "-";
}
int numGroups =( (cleaned.length() - remainder)/Key);
for (int i = 0; i < numGroups; i++) {
for (int k =0; k < Key; k++) {
char currentLetter = cleaned.charAt(currentPos++);
result = result + currentLetter;
}
if (i != (numGroups - 1)) {
result = result + "-";
}
}
}
//IF NOT EVENLY SPLIT
return result;
}
When I run it on my Computer, it works perfectly. When I run it on leetcode, it gives me a "Time Limit Exceeded" Error on the an input of a string of 44151 characters and "1" as the key. When I run the same input on my IDE, it works fine, but not on LeetCode. What might be the error? How could I make this more efficient?
I believe there is nothing wrong in program, but it is not the fast enough to meet time complexity expected by leetcode. I would suggest you can try, remove dashes and convert to upper cases. then add dashes at every (kth+remainder) places after the remainder position.
Do these operations in a stringbuilder instead of string.

How to capitalize every other letter in a string efficiently in java?

I'm currently working on a problem in code hunt level 6.02 which asks me to capitalize every other letter in a String. I have tried doing it with toCharArray + StringBuilder in for loops. It works, but it's not good enough. I still can't get the perfect score for the problem. I'm running out of ideas. Any help will be greatly appreciated.
Note: This is my first post on stack overflow. So if I miss anything or ask question in a wrong way. Pls feel free to point it out for me. Thx.
s is the input string
Attempt 1:
char [] words = s.toCharArray();
for (int i = 0; i < words.length; i +=2){
words[i] = Character.toUpperCase(words[i]);
}
return new String(words);
Attempt 2:
StringBuilder result = new StringBuilder(s);
for (int i = 0; i < result.length(); i +=2){
result.replace(i, i + 1, result.substring(i,i + 1).toUpperCase());
}
return result.toString();
Input: "iaiaa"
Expected output: "IaIaA"
In both of your attempts, you're going through the characters 2 1/2 times.
Taking your second attempt;
StringBuilder result = new StringBuilder(s);
for (int i = 0; i < result.length(); i +=2){
result.replace(i, i + 1, result.substring(i,i + 1).toUpperCase());
}
return result.toString();
The first line copies all the characters, and your last line copies all the characters. Your for loop goes through half the characters, for a total of 2 1/2 sets of characters.
I don't know if this is faster, but here's my attempt.
String r = "";
for (int i = 0; i < s.length; i++) {
if (i % 2 == 0) {
r += s.substring(i, i + 1).toUpperCase();
} else {
r += s.substring(i, i + 1);
}
}
return r;
I realize that this looks like a lot of intermediate Strings are created, but string concatenation has improved since Java 1.7.
I don't know how efficient this really is, but this does the trick for capitalizing the first letter and every other letter after.
String sentence = "i want to manipulate this string";
char[] array = new char[] {};
array = sentence.toCharArray(); //put the sentence into a character array
for (int i = 0; i < array.length; i += 2) {
if (array[i] == ' ') { //if the character is blank, move to the next index
i++;
}
array[i] = Character.toUpperCase(array[i]); //capitalize
}
sentence = new String(array); //revert array back to String
System.out.println(sentence); //display

Unsure how to implement for loop

Hello I am having trouble implementing this function
Function:
Decompress the String s. Character in the string is preceded by a number. The number tells you how many times to repeat the letter. return a new string.
"3d1v0m" becomes "dddv"
I realize my code is incorrect thus far. I am unsure on how to fix it.
My code thus far is :
int start = 0;
for(int j = 0; j < s.length(); j++){
if (s.isDigit(charAt(s.indexOf(j)) == true){
Integer.parseInt(s.substring(0, s.index(j))
Assuming the input is in correct format, the following can be a simple code using for loop. Of course this is not a stylish code and you may write more concise and functional style code using Commons Lang or Guava.
StringBuilder builder = new StringBuilder();
for (int i = 0; i < s.length(); i += 2) {
final int n = Character.getNumericValue(s.charAt(i));
for (int j = 0; j < n; j++) {
builder.append(s.charAt(i + 1));
}
}
System.out.println(builder.toString());
Here is a solution you may like to use that uses Regex:
String query = "3d1v0m";
StringBuilder result = new StringBuilder();
String[] digitsA = query.split("\\D+");
String[] letterA = query.split("[0-9]+");
for (int arrIndex = 0; arrIndex < digitsA.length; arrIndex++)
{
for (int count = 0; count < Integer.parseInt(digitsA[arrIndex]); count++)
{
result.append(letterA[arrIndex + 1]);
}
}
System.out.println(result);
Output
dddv
This solution is scalable to support more than 1 digit numbers and more than 1 letter patterns.
i.e.
Input
3vs1a10m
Output
vsvsvsammmmmmmmmm
Though Nami's answer is terse and good. I'm still adding my solution for variety, built as a static method, which does not use a nested For loop, instead, it uses a While loop. And, it requires that the input string has even number of characters and every odd positioned character in the compressed string is a number.
public static String decompress_string(String compressed_string)
{
String decompressed_string = "";
for(int i=0; i<compressed_string.length(); i = i+2) //Skip by 2 characters in the compressed string
{
if(compressed_string.substring(i, i+1).matches("\\d")) //Check for a number at odd positions
{
int reps = Integer.parseInt(compressed_string.substring(i, i+1)); //Take the first number
String character = compressed_string.substring(i+1, i+2); //Take the next character in sequence
int count = 1;
while(count<=reps)//check if at least one repetition is required
{
decompressed_string = decompressed_string + character; //append the character to end of string
count++;
};
}
else
{
//In case the first character of the code pair is not a number
//Or when the string has uneven number of characters
return("Incorrect compressed string!!");
}
}
return decompressed_string;
}

Categories