|
69 | 69 |
|
70 | 70 | ## Attempted solution(s)
|
71 | 71 | ```python
|
72 |
| -class Solution: |
73 |
| - def countOfAtoms(self, formula: str) -> str: |
74 |
| - def tokenize(formula): # double check logic here |
75 |
| - digits = '0123456789' |
76 |
| - lowercase = 'abcdefghijklmnopqrstuvwxyz' |
77 |
| - uppercase = lowercase.upper() |
78 |
| - parentheses = '()' |
| 72 | +import collections # thanks for pointing me to this, Paxton!! |
79 | 73 |
|
| 74 | +class Solution: |
| 75 | + def countOfAtoms(self, formula: str) -> str: |
| 76 | + def tokenize(formula): |
80 | 77 | tokens = []
|
81 |
| - t = '' |
82 |
| - for c in formula: |
83 |
| - if c in parentheses: |
84 |
| - tokens.append(c) |
85 |
| - t = '' |
86 |
| - elif c in uppercase: # note for later: need to fix this... |
87 |
| - if len(t) > 0: |
88 |
| - if t[0] in digits: |
89 |
| - t = int(t) |
90 |
| - tokens.append(t) |
91 |
| - t = c |
92 |
| - elif c in lowercase: |
93 |
| - t += c |
94 |
| - else: # c is a digit |
95 |
| - if len(t) > 0: |
96 |
| - if t[-1] in digits: |
97 |
| - t += c |
98 |
| - else: |
99 |
| - tokens.append(t) |
100 |
| - t = c |
| 78 | + i = 0 |
| 79 | + n = len(formula) |
| 80 | + while i < n: |
| 81 | + if formula[i].isupper(): |
| 82 | + start = i |
| 83 | + i += 1 |
| 84 | + while i < n and formula[i].islower(): |
| 85 | + i += 1 |
| 86 | + tokens.append(formula[start:i]) |
| 87 | + elif formula[i].isdigit(): |
| 88 | + start = i |
| 89 | + i += 1 |
| 90 | + while i < n and formula[i].isdigit(): |
| 91 | + i += 1 |
| 92 | + tokens.append(int(formula[start:i])) |
| 93 | + elif formula[i] in "()": |
| 94 | + tokens.append(formula[i]) |
| 95 | + i += 1 |
| 96 | + return tokens |
| 97 | + |
| 98 | + def multiply_dict(d, factor): |
| 99 | + for key in d: |
| 100 | + d[key] *= factor |
| 101 | + return d |
| 102 | + |
| 103 | + def merge_dicts(d1, d2): |
| 104 | + for key in d2: |
| 105 | + if key in d1: |
| 106 | + d1[key] += d2[key] |
| 107 | + else: |
| 108 | + d1[key] = d2[key] |
| 109 | + return d1 |
| 110 | + |
| 111 | + def count_atoms(tokens, offset=0): |
| 112 | + total_count = collections.defaultdict(int) |
| 113 | + i = offset |
| 114 | + while i < len(tokens): |
| 115 | + if isinstance(tokens[i], str) and tokens[i].isalpha(): |
| 116 | + elem = tokens[i] |
| 117 | + count = 1 |
| 118 | + if i + 1 < len(tokens) and isinstance(tokens[i + 1], int): |
| 119 | + count = tokens[i + 1] |
| 120 | + i += 1 |
| 121 | + total_count[elem] += count |
| 122 | + elif tokens[i] == "(": |
| 123 | + depth = 1 |
| 124 | + j = i + 1 |
| 125 | + while j < len(tokens) and depth > 0: |
| 126 | + if tokens[j] == "(": |
| 127 | + depth += 1 |
| 128 | + elif tokens[j] == ")": |
| 129 | + depth -= 1 |
| 130 | + j += 1 |
| 131 | + sub_count = count_atoms(tokens, i + 1) |
| 132 | + i = j - 1 |
| 133 | + if i + 1 < len(tokens) and isinstance(tokens[i + 1], int): |
| 134 | + count = tokens[i + 1] |
| 135 | + i += 1 |
101 | 136 | else:
|
102 |
| - t = c |
| 137 | + count = 1 |
| 138 | + multiply_dict(sub_count, count) |
| 139 | + merge_dicts(total_count, sub_count) |
| 140 | + elif tokens[i] == ")": |
| 141 | + return total_count |
| 142 | + i += 1 |
| 143 | + return total_count |
103 | 144 |
|
104 |
| - if len(t) > 0: |
105 |
| - if t[0] in digits: |
106 |
| - tokens.append(int(t)) |
107 |
| - else: |
108 |
| - tokens.append(t) |
| 145 | + tokens = tokenize(formula) |
| 146 | + atom_counts = count_atoms(tokens) |
109 | 147 |
|
110 |
| - return tokens |
| 148 | + sorted_atoms = sorted(atom_counts.items()) |
| 149 | + result = [] |
| 150 | + for atom, count in sorted_atoms: |
| 151 | + result.append(atom) |
| 152 | + if count > 1: |
| 153 | + result.append(str(count)) |
| 154 | + |
| 155 | + return ''.join(result) |
111 | 156 | ```
|
| 157 | +- Given test cases: pass |
| 158 | +- Need to stop for today, so no time to test other cases...just submitting |
| 159 | + |
| 160 | + |
| 161 | +- meh... |
| 162 | +- maybe a stack would have been better than a recursive solution? would have avoided copying... |
| 163 | + |
0 commit comments