CodeWars 일백 아홉 번째 문제

Updated:

Molecule to atoms

static class RawForm extends HashMap<String, Integer> {
    public RawForm() {
        super();
    }

    public void addAtom(final String atom, final int n) {
        this.put(atom, n + this.getOrDefault(atom, 0));
    }

    public RawForm mulBy(final int n) {
        this.forEach((at, v) -> this.put(at, v * n));
        return this;
    }

    public RawForm concatWith(RawForm other) {
        other.forEach((at, v) -> this.put(at, v + this.getOrDefault(at, 0)));
        return this;
    }
}

private static Iterator<String> tokenIter;
private static Stack<Integer> bracketStk;

private static final String AT_NUM = "[A-Z][a-z]?\\d*";
private static final String OPEN_BRA = "[{(\\[]";
private static final String CLOSE_BRA = "[)}\\]]\\d*";
private static final Pattern TOKENIZER = Pattern.compile(String.format("%s|%s|%s", AT_NUM, OPEN_BRA, CLOSE_BRA));
private static final Pattern P_AT_NUM = Pattern.compile("(?<at>[A-Z][a-z]*)(?<num>\\d*)");

public static Map<String, Integer> getAtoms(String formula) {

    List<String> tokens = new ArrayList<String>();
    Matcher m = TOKENIZER.matcher(formula);
    while (m.find())
        tokens.add(m.group());

    if (!String.join("", tokens).equals(formula))
        throw new IllegalArgumentException("Invalid formula");

    bracketStk = new Stack<Integer>();
    tokenIter = tokens.iterator();

    RawForm ans = getRawFormula();
    if (!bracketStk.empty())
        throw new IllegalArgumentException("Invalid formula");

    return ans;
}

private static RawForm getRawFormula() {

    RawForm raw = new RawForm();

    while (tokenIter.hasNext()) {
        String tok = tokenIter.next();

        if (tok.matches(OPEN_BRA)) {
            bracketStk.push((int) tok.charAt(0));
            raw.concatWith(getRawFormula());

        } else if (tok.matches(AT_NUM)) {
            Matcher m = P_AT_NUM.matcher(tok);
            m.find();
            raw.addAtom(m.group("at"), m.group("num").isEmpty() ? 1 : Integer.parseInt(m.group("num")));

        } else if (tok.matches(CLOSE_BRA)) {
            if (bracketStk.empty() || (bracketStk.peek() + 1 != (int) tok.charAt(0)
                                       && bracketStk.peek() + 2 != (int) tok.charAt(0)))
                throw new IllegalArgumentException("Invalid formula");
            bracketStk.pop();

            if (tok.length() > 1)
                raw.mulBy(Integer.parseInt(tok.substring(1)));
            break;
        }
    }
    return raw;
}
  • 일단 이번 문제는 풀지 못했다. 답이 쉬울줄 알았는데 정말 어려웠다. 문제 수준이 5kyu는 아닌것 같다. 내가 볼때 최소 4kyu아님 3kyu인것 같다.
  • 다른 Best 코드들을 봤는데 위에 코드처럼 깔끔하게 푼게 하나도 없었다. 위의 문제도 정규식에 대해서 빠삭하게 알고 있어야 풀 수 있는 문제였다.
  • 내가 pattern에 대해서 익숙치 않아서 이번 기회에 공부좀 해야겠다.