Bug
Bug

Reputation: 137

how to reverse only numbers in a string

INPUT : 123ABC458 OUTPUT : 321ABC854

public static void main(String []args){
    String str="123ABC564";
    int count=0;
    int ans=0;
    int firstindex=0;
    char[] ch = str.toCharArray();
    for(int i=0;i<ch.length;i++){
        if(Character.isDigit(ch[i])){
            if(ans==0){
                firstindex=i;

            }
            count++;
        }
        else{
            int lastindex=count+firstindex-1;
            while(firstindex<lastindex){
                char temp=ch[firstindex];
                ch[firstindex]=ch[lastindex];
                ch[lastindex]=temp;
                firstindex++;
                lastindex--;
            }
            ans=0;
            count=0;
            firstindex=0;
        }
    }
    for (char c : ch){
        System.out.print(c);
    }
}

}

Can anyone tell me what's wrong with this code The output which I am getting using this code is 12BA3C564

Upvotes: 3

Views: 3071

Answers (6)

The fourth bird
The fourth bird

Reputation: 163287

As an alternative solution, from Java 9 you could also make use of Matcher#replaceAll and reverse every match for 1 or more digits.

String result = Pattern.compile("\\d+")
    .matcher("123ABC458")
    .replaceAll(m -> new StringBuilder(m.group()).reverse().toString());

System.out.println(result);

Output

321ABC854

Java demo

Upvotes: 0

Melron
Melron

Reputation: 579

You can get all the numbers from the string as the first move, and then replace the input with the reversed string of the numbers. Example:

public static void main(String[] args)
{
    String input = "123ABC458";
    Matcher m = Pattern.compile("\\d+").matcher(input);
    while(m.find()) 
        input = input.replace(m.group(), new StringBuilder(m.group()).reverse());
    
    System.out.println(input);
}

Upvotes: 0

Anonymous
Anonymous

Reputation: 86272

Can anyone tell me what's wrong with this code

I believe I have spotted two bugs in your code:

  1. You are never setting ans to anything else than 0. So your if condition ans==0 will always be true. If I have understood the purpose of that variable correctly, you may want to replace it with a boolean called something like insideNumber and set it to true when you detect a digit and to false when you detect that a char is not a digit. Your if statement then becomes if (insideNumber)
  2. You don’t take a number at the end of your string into account. You can check this statement by appending a letter to your string and see that 564 will then be reversed into 465. To reverse a trailing number correctly: after your loop again check whether you were inside a number, and if so, reverse the last number from firstindex up to the end of the string.

Upvotes: 1

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79075

You can use the Java regex API and StringBuilder to solve it easily. The regex, \d+ specifies one or more digits. Using the Java regex API, you find the numbers, their start position and the end positions which you can use to build the required string.

Demo:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        // Tests
        String[] samples = { "123ABC458", "123ABC458XYZ", "123ABC458XYZ367", "ABC123XYZ", "ABC123XYZ" };
        for (String s : samples)
            System.out.println(numbersInverted(s));

    }

    static String numbersInverted(String str) {
        StringBuilder sb = new StringBuilder();
        Matcher matcher = Pattern.compile("\\d+").matcher(str);
        int lastInitialPos = 0;
        while (matcher.find()) {
            int start = matcher.start();
            String inverted = new StringBuilder(matcher.group()).reverse().toString();
            sb.append(str.substring(lastInitialPos, start)).append(inverted);
            lastInitialPos = matcher.end();
        }
        if (sb.length() == 0) // If no number was found
            return str;
        else
            return sb.append(str.substring(lastInitialPos)).toString();
    }
}

Output:

321ABC854
321ABC854XYZ
321ABC854XYZ763
ABC321XYZ
ABC321XYZ

ONLINE DEMO

Upvotes: 1

Nowhere Man
Nowhere Man

Reputation: 19545

This task can be implemented without regular expressions, splitting the input string into substring etc. merely with the help of StringBuilder::insert(int offset, char c) and StringBuilder::append(char c) using simple index calculation for insert:

public static String revertDigits(String str) {
    if (str == null || str.isEmpty()) {
        return str;
    }

    StringBuilder sb = new StringBuilder(str.length());
    
    for (int i = 0, j = 0, n = str.length(); i < n; i++) {
        char c = str.charAt(i);
        if (Character.isDigit(c)) {
            sb.insert(j, c); // append in "reverse" mode
        } else {
            sb.append(c);
            j = i + 1;  // store the last position of a non-digit
        }
    }
    
    return sb.toString();
}

Test:

String str="123ABC564";

System.out.println(str + '\n' + revertDigits(str));

Output

123ABC564
321ABC465

Upvotes: 1

Tim Biegeleisen
Tim Biegeleisen

Reputation: 521178

Here is a concise version using string splitting:

String input = "123ABC458";
String[] parts = input.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
StringBuilder sb = new StringBuilder();
for (String part : parts) {
    if (part.matches("\\d+")) {
        StringBuilder num = new StringBuilder(part);
        sb.append(num.reverse());
    }
    else {
        sb.append(part);
    }
}

System.out.println(sb.toString());  // 321ABC854

The splitting operation used above generates a string array of either numbers or letters. Then, we iterate that array and selectively reverse the number strings using StringBuilder#reverse.

Upvotes: 1

Related Questions