fork download
  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. import java.util.HashMap;
  5. import java.util.Iterator;
  6. import java.util.Map;
  7. import java.util.Map.Entry;
  8. import java.util.Set;
  9. import java.util.Vector;
  10. import java.util.concurrent.atomic.AtomicInteger;
  11.  
  12. public class Main {
  13.  
  14. /**
  15. * Only supports element numbers that are one/two digit(s)...
  16. * @param args
  17. */
  18. public static void main(String[] args) {
  19. String line;
  20. while ((line = br.readLine()) != null) {
  21. evaluate(line, expand(line));
  22. }
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. } catch (NumberFormatException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29.  
  30. /**
  31. * Counts the number of elements in a chemical formula
  32. * @param line: Line consisting of the elements
  33. */
  34. private static void evaluate(String orig, String line) {
  35. Map<String, AtomicInteger> map = new HashMap<String, AtomicInteger>();
  36. for (int i = 0; i < line.length(); i++) {
  37. char cur = line.charAt(i);
  38. if (i + 1 < line.length()) {
  39. char next = line.charAt(i + 1);
  40. if (next >= 'A' && next <= 'Z') {
  41. String ele = new StringBuilder("").append(cur).toString();
  42. if (map.containsKey(ele)) {
  43. map.get(ele).incrementAndGet();
  44. } else {
  45. map.put(ele, new AtomicInteger(1));
  46. }
  47. } else if (next >= 'a' && next <= 'z') {
  48. if (i + 2 < line.length()) {
  49. char possibleNum = line.charAt(i + 2);
  50. int possibleNum2 = -1;
  51. if (i + 3 < line.length())
  52. possibleNum2 = (int) line.charAt(i + 3);
  53. String ele = new StringBuilder("").append(cur).append(next).toString();
  54. if (possibleNum >= '0' && possibleNum <= '9') {
  55. StringBuilder number = new StringBuilder("").append(possibleNum);
  56. if ((char) possibleNum2 >= '0' && (char) possibleNum2 <= '9') {
  57. number.append((char) possibleNum2);
  58. i++;
  59. }
  60. int num = Integer.parseInt(number.toString());
  61. if (map.containsKey(ele)) {
  62. for (int j = 0; j < num; j++)
  63. map.get(ele).incrementAndGet();
  64. } else {
  65. map.put(ele, new AtomicInteger(num));
  66. }
  67. i += 2;
  68. } else {
  69. if (map.containsKey(ele)) {
  70. map.get(ele).incrementAndGet();
  71. } else {
  72. map.put(ele, new AtomicInteger(1));
  73. }
  74. i++;
  75. }
  76. } else {
  77. String ele = new StringBuilder("").append(cur).append(next).toString();
  78. if (map.containsKey(ele)) {
  79. map.get(ele).incrementAndGet();
  80. } else {
  81. map.put(ele, new AtomicInteger(1));
  82.  
  83. }
  84. i++;
  85. }
  86. } else if (next >= '0' && next <= '9') {
  87. String ele = new StringBuilder("").append(cur).toString();
  88. StringBuilder number = new StringBuilder("").append(next);
  89.  
  90. if (i + 2 < line.length()) {
  91. if (line.charAt(i + 2) >= '0' && line.charAt(i + 2) <= '9') {
  92. number.append(line.charAt(i + 2));
  93. i++;
  94. }
  95. }
  96. int num = Integer.parseInt(number.toString());
  97. if (map.containsKey(cur + "")) {
  98. for (int j = 0; j < num; j++)
  99. map.get(ele).incrementAndGet();
  100. } else {
  101. map.put(ele, new AtomicInteger(num));
  102. }
  103. i++;
  104. }
  105. } else {
  106. // we are on the last element, it must be a single letter
  107. String ele = new StringBuilder("").append(cur).toString();
  108. if (map.containsKey(ele)) {
  109. map.get(ele).incrementAndGet();
  110. } else {
  111. map.put(ele, new AtomicInteger(1));
  112. }
  113. }
  114. }
  115.  
  116. print(orig, map);
  117. }
  118.  
  119. /**
  120. * Prints the map
  121. * @param line
  122. * @param map
  123. */
  124. private static void print(String line, Map<String, AtomicInteger> map) {
  125. System.out.printf("%s\n", line);
  126. Set<Entry<String, AtomicInteger>> entries = map.entrySet();
  127. Iterator<Entry<String, AtomicInteger>> it = entries.iterator();
  128. while (it.hasNext()) {
  129. Entry<String, AtomicInteger> e = it.next();
  130. System.out.println("\t" + e.getKey() + ": " + e.getValue().get());
  131. }
  132. System.out.printf("\n");
  133. }
  134.  
  135. /**
  136. * Method expands 'tougher' chemical compounds consisting of
  137. * multiple inner molecules
  138. *
  139. * I.E.
  140. * C4H8(OH)2 -> C4H8OHOH
  141. * @param line: Line consisting of the elements
  142. * @return String: expanded line
  143. *
  144. * PRECONDITION: Parentheses are balanced and contain at least
  145. * one element
  146. */
  147. private static String expand(String line) throws NumberFormatException {
  148. if (!line.contains("("))
  149. return line;
  150. // find the indexes of the parentheses and create a
  151. // stringbuilder object
  152. Vector<Integer> vec = getOpenClose(line);
  153. int open = vec.get(0);
  154. int closed = vec.get(1);
  155. StringBuilder newString = new StringBuilder("");
  156.  
  157. // append the beginning of the formula
  158. for (int i = 0; i < open; i++) {
  159. newString.append(line.charAt(i));
  160. }
  161.  
  162. // repeat the elements in the parenthese's the repeated
  163. // number of times
  164. int repeat = Integer.parseInt(line.charAt(closed + 1) + "");
  165. for (int i = 0; i < repeat; i++) {
  166. for (int j = open + 1; j < closed; j++) {
  167. newString.append(line.charAt(j));
  168. }
  169. }
  170.  
  171. // append the rest of the string onto the new string
  172. for (int i = closed + 2; i < line.length(); i++) {
  173. newString.append(line.charAt(i));
  174. }
  175.  
  176. // recurse through in case we have another pair of parentheses
  177. return expand(newString.toString());
  178. }
  179.  
  180. /**
  181. * Gets the index of the inner-most set of parentheses
  182. * @param line: line to search
  183. * @return Vector<Integer>: vector of the two indexes
  184. */
  185. public static Vector<Integer> getOpenClose(String line) {
  186. Vector<Integer> vec = new Vector<Integer>();
  187. int open = -1;
  188. int closed = -1;
  189. for (int i = 0; i < line.length(); i++) {
  190. if (line.charAt(i) == ')') {
  191. closed = i;
  192. break;
  193. }
  194. }
  195. stop: for (int i = closed; i >= 0; i--) {
  196. if (line.charAt(i) == '(') {
  197. open = i;
  198. break stop;
  199. }
  200. }
  201.  
  202. vec.add(0, open);
  203. vec.add(1, closed);
  204. return vec;
  205. }
  206. }
Success #stdin #stdout 0.05s 4386816KB
stdin
C6H12O6
CCl2F2
NaHCO3
C4H8(OH)2
PbCl(NH3)2(COOH)2
stdout
C6H12O6
	C: 6
	H: 12
	O: 6

CCl2F2
	C: 1
	F: 2
	Cl: 2

NaHCO3
	Na: 1
	C: 1
	H: 1
	O: 3

C4H8(OH)2
	C: 4
	H: 10
	O: 2

PbCl(NH3)2(COOH)2
	Pb: 1
	C: 2
	H: 8
	Cl: 1
	N: 2
	O: 4