import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
/**
* Only supports element numbers that are one/two digit(s)...
* @param args
*/
public static void main
(String[] args
) { while ((line = br.readLine()) != null) {
evaluate(line, expand(line));
}
e.printStackTrace();
e.printStackTrace();
}
}
/**
* Counts the number of elements in a chemical formula
* @param line: Line consisting of the elements
*/
Map
<String, AtomicInteger
> map
= new HashMap
<String, AtomicInteger
>(); for (int i = 0; i < line.length(); i++) {
char cur = line.charAt(i);
if (i + 1 < line.length()) {
char next = line.charAt(i + 1);
if (next >= 'A' && next <= 'Z') {
String ele
= new StringBuilder
("").
append(cur
).
toString(); if (map.containsKey(ele)) {
map.get(ele).incrementAndGet();
} else {
map.put(ele, new AtomicInteger(1));
}
} else if (next >= 'a' && next <= 'z') {
if (i + 2 < line.length()) {
char possibleNum = line.charAt(i + 2);
int possibleNum2 = -1;
if (i + 3 < line.length())
possibleNum2 = (int) line.charAt(i + 3);
String ele
= new StringBuilder
("").
append(cur
).
append(next
).
toString(); if (possibleNum >= '0' && possibleNum <= '9') {
StringBuilder number = new StringBuilder("").append(possibleNum);
if ((char) possibleNum2 >= '0' && (char) possibleNum2 <= '9') {
number.append((char) possibleNum2);
i++;
}
int num
= Integer.
parseInt(number.
toString()); if (map.containsKey(ele)) {
for (int j = 0; j < num; j++)
map.get(ele).incrementAndGet();
} else {
map.put(ele, new AtomicInteger(num));
}
i += 2;
} else {
if (map.containsKey(ele)) {
map.get(ele).incrementAndGet();
} else {
map.put(ele, new AtomicInteger(1));
}
i++;
}
} else {
String ele
= new StringBuilder
("").
append(cur
).
append(next
).
toString(); if (map.containsKey(ele)) {
map.get(ele).incrementAndGet();
} else {
map.put(ele, new AtomicInteger(1));
}
i++;
}
} else if (next >= '0' && next <= '9') {
String ele
= new StringBuilder
("").
append(cur
).
toString(); StringBuilder number = new StringBuilder("").append(next);
if (i + 2 < line.length()) {
if (line.charAt(i + 2) >= '0' && line.charAt(i + 2) <= '9') {
number.append(line.charAt(i + 2));
i++;
}
}
int num
= Integer.
parseInt(number.
toString()); if (map.containsKey(cur + "")) {
for (int j = 0; j < num; j++)
map.get(ele).incrementAndGet();
} else {
map.put(ele, new AtomicInteger(num));
}
i++;
}
} else {
// we are on the last element, it must be a single letter
String ele
= new StringBuilder
("").
append(cur
).
toString(); if (map.containsKey(ele)) {
map.get(ele).incrementAndGet();
} else {
map.put(ele, new AtomicInteger(1));
}
}
}
print(orig, map);
}
/**
* Prints the map
* @param line
* @param map
*/
private static void print
(String line, Map
<String, AtomicInteger
> map
) { System.
out.
printf("%s\n", line
); Set
<Entry
<String, AtomicInteger
>> entries
= map.
entrySet(); Iterator
<Entry
<String, AtomicInteger
>> it
= entries.
iterator(); while (it.hasNext()) {
Entry
<String, AtomicInteger
> e
= it.
next(); System.
out.
println("\t" + e.
getKey() + ": " + e.
getValue().
get()); }
}
/**
* Method expands 'tougher' chemical compounds consisting of
* multiple inner molecules
*
* I.E.
* C4H8(OH)2 -> C4H8OHOH
* @param line: Line consisting of the elements
* @return String: expanded line
*
* PRECONDITION: Parentheses are balanced and contain at least
* one element
*/
if (!line.contains("("))
return line;
// find the indexes of the parentheses and create a
// stringbuilder object
Vector<Integer> vec = getOpenClose(line);
int open = vec.get(0);
int closed = vec.get(1);
StringBuilder newString = new StringBuilder("");
// append the beginning of the formula
for (int i = 0; i < open; i++) {
newString.append(line.charAt(i));
}
// repeat the elements in the parenthese's the repeated
// number of times
int repeat
= Integer.
parseInt(line.
charAt(closed
+ 1) + ""); for (int i = 0; i < repeat; i++) {
for (int j = open + 1; j < closed; j++) {
newString.append(line.charAt(j));
}
}
// append the rest of the string onto the new string
for (int i = closed + 2; i < line.length(); i++) {
newString.append(line.charAt(i));
}
// recurse through in case we have another pair of parentheses
return expand(newString.toString());
}
/**
* Gets the index of the inner-most set of parentheses
* @param line: line to search
* @return Vector<Integer>: vector of the two indexes
*/
public static Vector
<Integer
> getOpenClose
(String line
) { Vector<Integer> vec = new Vector<Integer>();
int open = -1;
int closed = -1;
for (int i = 0; i < line.length(); i++) {
if (line.charAt(i) == ')') {
closed = i;
break;
}
}
stop: for (int i = closed; i >= 0; i--) {
if (line.charAt(i) == '(') {
open = i;
break stop;
}
}
vec.add(0, open);
vec.add(1, closed);
return vec;
}
}