Повторение символов N количество раз (задачка)

Есть задача повторить символы внутри квадратных скобок определенное количество раз. Входные данные выглядят след образом, строка содержащая 3[a] на выходе должно получиться aaa, 3[a]2[y] = aaayy. Но запись может быть и такой 3[2[a]y] на выходе должно получится aayaayaay.

Мой исходник ниже решает проблему с 3[2[a]] но не может справится с 3[2[a]y].

public class Main {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String line = scanner.nextLine();


        System.out.println(DoApr(line));
 
    }

    public static String DoApr(String arg) {
        char[] chars = arg.toCharArray();
        String output1 = "";
        for (int i = 0; i < chars.length; i++) {
            if (isHasArr(chars)){
                if (isNumeric(String.valueOf(chars[i]))) {
                        int start = i + 2;
                        int end = FindEnd(chars, start);
                        if (end != 0) {
                            String str = "";
                            String output = "";
                            for (int g = start; g < end + 1; g++) {
                                str += String.valueOf(chars[g]);
                            }
                            if (str.contains("[")){
                                str = DoApr(str);
                            }
                            if (!str.contains("[")){
                                for (int c = 0; c < Integer.parseInt(String.valueOf(chars[i])); c++) {
                                    output1 += str.replace("]","");
                                }
                            }
                        }
                    }
            }
        }
        return output1;
    }

    public static int FindEnd(char[] chars, int startIndex) {
        for (int i = startIndex + 1; i < chars.length; i++) {
            if (chars[i] == ']') {
                return i;
            }
        }
        return 0;
    }

    public static boolean isNumeric(String strNum) {
        if (strNum == null) {
            return false;
        }
        try {
            double d = Double.parseDouble(strNum);
        } catch (NumberFormatException nfe) {
            return false;
        }
        return true;
    }

    public static boolean isHasArr(char[] chars){
        boolean hasornot = false;
        for (int i = 0 ; i < chars.length;i++){
            if (String.valueOf(chars[i]).equals("[")){
                hasornot = true;
            }
        }
        return hasornot;
    }

}

Есть ли тут какое нибудь решение ?


Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

Первое что бросается в глаза - нет обработки вложенных скобок. Просто так не исправить, нужно переделать всю работу.

Это задача на скобочную структуру. А где скобочная структура, там стек (или рекурсия, но у нас будет стек).

Входной поток обрабатывается посимвольно. Если встретилась открывающая скобка, то в стек помещается запись с множителем. Если - буква, то добавляем её в верхний элемент стека, тоже с множителем. Если - закрывающая скобка, то запись из стека извлекается, а текст, который получился между скобками, вставляется в следующий элемент стека, опять-таки с множителем. Цифры обрабатываются отдельно: в каждый момент времени хранится множитель для следующего элемента.

Если в стеке ничего нет, то букву печатаем на выход. И снова множитель не забываем:

import java.io.IOException;
import java.util.Stack;

public class Inflator {
    private static class Item {
        public final int factor;
        public final StringBuilder sb;
        public Item(int factor) {
            this.factor = factor;
            sb = new StringBuilder();
        }
    };
    private static Stack<Item> stack = new Stack<Item>();

    public static void main(String... args) {
        int c = -1;
        int factor = 0;
        for (; ; ) {
            try {
                c = System.in.read();
            } catch (IOException e) {
                System.exit(1);
            }
            if (c == -1) {
                break;
            }
            if (Character.isDigit(c)) {
                factor = 10 * factor + Character.getNumericValue(c);
            } else if (c == '[') {
                stack.push(new Item(factor));
                factor = 0;
            } else if (c == ']') {
                Item item = stack.pop();
                String s = item.sb.toString();
                append(item.factor, s);
                factor = 0;
            } else {
                append(factor, Character.toString((char) c));
                factor = 0;
            }
        }
    }

    private static void append(int factor, String s) {
        int n = (factor == 0) ? 1 : factor;
        for (int i = 0; i < n; ++i) {
            if (stack.empty()) {
                System.out.print(s);
            } else {
                stack.peek().sb.append(s);
            }
        }
    }
}
$ javac Inflator.java && java Inflator 
3a
aaa


33a
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa


3[a]2[y]
aaayy


3[2[a]y]
aayaayaay


3[2[a]]
aaaaaa


2[2[2[2[2[a]]]]]
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa


2[2[2[2[2[2[a]]]]]]
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
→ Ссылка