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에 대해서 익숙치 않아서 이번 기회에 공부좀 해야겠다.