patternjavaMinor
String 'expanding' - reinserting repeating characters
Viewed 0 times
expandingreinsertingrepeatingcharactersstring
Problem
The challenge: Given a String, for each digit in that original string, replace that digit with that many occurrences of the character following it. So
My Solution:
Could this be more readable? I alternate a lot between char and string (it seems optimal, am I wrong?), but should I just stick with one? Any and all feedback/suggested revisions/general optimizations welcomed with gratitude.
Edit: Stay within the specifications of the challenge. In the case of a number following a number this code is WAI i.e. the correct yield of blowup("a231") results in "a33111."
Edit 2: End digits just get ignored, since they have nothing to repeat, i.e. blowup("a2x3") would yield "axxx" - I re
a3tx2z yields attttxzzz.My Solution:
import java.util.Scanner;
public class Standford1 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter string to blowup: ");
String userInput = input.nextLine();
System.out.println(blowup(userInput));
}
public static String blowup(String str) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
if (!isNumeric(str.substring(i, i + 1))) {
sb.append(str.charAt(i));
}
else {
sb.append(lengthen(str.charAt(i + 1),
Integer.parseInt(str.substring(i, i + 1))));
}
}
return sb.toString();
}
public static boolean isNumeric(String str) {
try {
int num = Integer.parseInt(str);
}
catch(NumberFormatException nfe) {
return false;
}
return true;
}
public static String lengthen(char c, int i){
if (i == 0 || c == ' ') { return ""; }
int count = 0;
StringBuilder sb = new StringBuilder(c);
while (count != i) {
sb.append(c);
count++;
}
return sb.toString();
}
}Could this be more readable? I alternate a lot between char and string (it seems optimal, am I wrong?), but should I just stick with one? Any and all feedback/suggested revisions/general optimizations welcomed with gratitude.
Edit: Stay within the specifications of the challenge. In the case of a number following a number this code is WAI i.e. the correct yield of blowup("a231") results in "a33111."
Edit 2: End digits just get ignored, since they have nothing to repeat, i.e. blowup("a2x3") would yield "axxx" - I re
Solution
Your instincts are good here, in almost all respects. Your basic algorithm is good, and your suspicions that you are changing too often between
Using the
With that function, you can throw out your
(I put this in an Ideone here)
Note that it also keeps a counter outside the loop. This removes the need for the 'ugly'
The code still assumes valid input (where the last character cannot be a digit, or it is lost). Additionally, I tweaked it to handle multiple digit input.... like
Update: In my mind, I immediately 'threw out' your
You should never use exception handling (
Update 2: working with the original specs (thus ignoring the multi-digit repeat), the code would be (here in a different Ideone):
Notes for this version:
String and char is also good.Using the
StringBuilder is the right thing to do; well done. Breaking the String into chars is also good, but the way you do that is inconvenient.... In part that's because there is a convenient function in the standard Java Character class that you will find useful: Character.isDigit(char)With that function, you can throw out your
isNumber() function, and simplify the whole thing down to chars, strings, and ints.... something like:public static String blowup(String str) {
StringBuilder sb = new StringBuilder();
int repeat = 0;
for (char c : str.toCharArray()) {
if (Character.isDigit(c)) {
repeat = repeat * 10 + Character.getNumericValue(c);
} else {
while (repeat > 0) {
sb.append(c);
repeat--;
}
sb.append(c);
}
}
return sb.toString();
}(I put this in an Ideone here)
Note that it also keeps a counter outside the loop. This removes the need for the 'ugly'
i + 1 offset on a repeating character count.The code still assumes valid input (where the last character cannot be a digit, or it is lost). Additionally, I tweaked it to handle multiple digit input.... like
"20z" ... for fun.Update: In my mind, I immediately 'threw out' your
isNumeric() method, because it was not needed... but I have only now just read it.... Eeugh! Yuck!You should never use exception handling (
try/catch) to handle normal program flow. The try/parse/catch logic you have is very slow to run. Throwing an exception for every non-digit character will be a lot of overhead. Even though Java has improved in terms of performance, when processing exceptions, it is still much slower than the alternatives, like a regular expression, or some other mechanism...Update 2: working with the original specs (thus ignoring the multi-digit repeat), the code would be (here in a different Ideone):
public static String blowup(String str) {
StringBuilder sb = new StringBuilder();
int repeat = -1;
for (char c : str.toCharArray()) {
if (repeat = 0);
}
}
return sb.toString();
}Notes for this version:
- Uses
repeatas a flag set to negative for nothing. This allows for input likeab01which will outputab1(which would be impossible without the 0-repeat option).
- Note that the repeat is now also used as a flag for the
isDigitcheck.
- a
do-whileloop instead of awhile-doloop (as per Josay's comment).
Code Snippets
public static String blowup(String str) {
StringBuilder sb = new StringBuilder();
int repeat = 0;
for (char c : str.toCharArray()) {
if (Character.isDigit(c)) {
repeat = repeat * 10 + Character.getNumericValue(c);
} else {
while (repeat > 0) {
sb.append(c);
repeat--;
}
sb.append(c);
}
}
return sb.toString();
}public static String blowup(String str) {
StringBuilder sb = new StringBuilder();
int repeat = -1;
for (char c : str.toCharArray()) {
if (repeat < 0 && Character.isDigit(c)) {
repeat = Character.getNumericValue(c);
} else {
do {
sb.append(c);
} while (--repeat >= 0);
}
}
return sb.toString();
}Context
StackExchange Code Review Q#75094, answer score: 6
Revisions (0)
No revisions yet.