HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

String 'expanding' - reinserting repeating characters

Submitted by: @import:stackexchange-codereview··
0
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 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 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 repeat as a flag set to negative for nothing. This allows for input like ab01 which will output ab1 (which would be impossible without the 0-repeat option).



  • Note that the repeat is now also used as a flag for the isDigit check.



  • a do-while loop instead of a while-do loop (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.