1
+ use std:: collections:: HashMap ;
2
+
3
+ impl Solution {
4
+ pub fn count_of_atoms ( formula : String ) -> String {
5
+ if formula. is_empty ( ) {
6
+ return "" . to_owned ( ) ;
7
+ }
8
+ let m = Self :: count ( formula. as_bytes ( ) ) ;
9
+ if m. is_none ( ) {
10
+ return "" . to_owned ( ) ;
11
+ }
12
+ let m = m. unwrap ( ) ;
13
+ let mut arr: Vec < ( & str , i32 ) > = m. into_iter ( ) . map ( |v| v) . collect ( ) ;
14
+ arr. sort_by ( |( s1, _) , ( s2, _) | s1. cmp ( s2) ) ;
15
+ let mut ans = vec ! [ ] ;
16
+ for ( k, v) in arr {
17
+ ans. push ( k. to_string ( ) ) ;
18
+ if v > 1 {
19
+ ans. push ( v. to_string ( ) ) ;
20
+ }
21
+ }
22
+ ans. join ( "" )
23
+ }
24
+ fn count ( s : & [ u8 ] ) -> Option < HashMap < & str , i32 > > {
25
+ if s. is_empty ( ) {
26
+ return None ;
27
+ }
28
+ let mut ans = HashMap :: new ( ) ;
29
+ let mut i = 0 ;
30
+ let n = s. len ( ) ;
31
+ while i < n {
32
+ if s[ i] == b'(' {
33
+ let mut count = 1 ;
34
+ let mut j = i+1 ;
35
+ while j < n {
36
+ if s[ j] == b'(' {
37
+ count+=1 ;
38
+ } else if s[ j] == b')' {
39
+ count -= 1 ;
40
+ }
41
+ if count == 0 {
42
+ break ;
43
+ }
44
+ j += 1 ;
45
+ }
46
+ let mut k = j+1 ;
47
+ let mut times = 0 ;
48
+ while k < n {
49
+ if s[ k] >= b'0' && s[ k] <= b'9' {
50
+ times = times* 10 + ( ( s[ k] -b'0' ) as i32 ) ;
51
+ k += 1 ;
52
+ } else {
53
+ break ;
54
+ }
55
+ }
56
+ if times == 0 {
57
+ times = 1 ;
58
+ }
59
+ if let Some ( inner) = Self :: count ( & s[ i+1 ..j] ) {
60
+ for ( k, v) in inner {
61
+ * ans. entry ( k) . or_insert ( 0 ) += v* times;
62
+ }
63
+ }
64
+ i = k;
65
+ } else {
66
+ let mut j = i+1 ;
67
+ while j < n {
68
+ if s[ j] >= b'a' && s[ j] <= b'z' {
69
+ j+=1 ;
70
+ } else {
71
+ break ;
72
+ }
73
+ }
74
+ let mut times = 0 ;
75
+ let mut k = j;
76
+ while k < n {
77
+ if s[ k] >= b'0' && s[ k] <=b'9' {
78
+ times = times* 10 + ( ( s[ k] -b'0' ) as i32 ) ;
79
+ k+=1 ;
80
+ } else {
81
+ break ;
82
+ }
83
+ }
84
+ if times == 0 {
85
+ times = 1 ;
86
+ }
87
+ * ans. entry ( unsafe { std:: str:: from_utf8_unchecked ( & s[ i..j] ) } ) . or_insert ( 0 ) += times;
88
+ i = k;
89
+ }
90
+ }
91
+ Some ( ans)
92
+ }
93
+ }
94
+
95
+ struct Solution ;
96
+
97
+ #[ cfg( test) ]
98
+ mod tests {
99
+ use super :: Solution ;
100
+
101
+ #[ test]
102
+ fn test_count_of_atoms ( ) {
103
+ let test_cases = vec ! [
104
+ ( "H2O" , "H2O" ) ,
105
+ ( "Mg(OH)2" , "H2MgO2" ) ,
106
+ ( "K4(ON(SO3)2)2" , "K4N2O14S4" ) ,
107
+ ] ;
108
+ for ( formula, expect) in test_cases {
109
+ assert_eq ! ( Solution :: count_of_atoms( formula. to_string( ) ) , expect, "formula: {}" , formula) ;
110
+ }
111
+ }
112
+ }
0 commit comments