Stack of Map | State Machine | OOP | Very clean
Approach\nSimple approach with Stack of Map and State Machine\n\n# Complexity\n- Time complexity: O(n)\n\n- Space complexity: O(n)\n\n# Code\ngo\nimport (\n\t"g
# Approach\nSimple approach with Stack of Map and State Machine\n\n# Complexity\n- Time complexity: O(n)\n\n- Space complexity: O(n)\n\n# Code\n```go\nimport (\n\t"github.com/emirpasic/gods/v2/stacks"\n\t"github.com/emirpasic/gods/v2/stacks/linkedliststack"\n)\n\n// https://leetcode.com/problems/number-of-atoms/\nfunc countOfAtoms(formula string) string {\n\tsm := NewStateMachine(formula)\n\tfor i := 0; i < sm.Len(); i++ {\n\t\tsm.Process(&i)\n\t}\n\treturn sm.PeakGroup().String()\n}\n\ntype State int\n\nconst (\n\tOpen State = iota\n\tClose\n)\n\ntype StateMachine struct {\n\tformula string\n\tcurEle  string\n\tstate   State\n\tstack   stacks.Stack[*ElementGroup]\n}\n\nfunc NewStateMachine(formula string) *StateMachine {\n\ts := linkedliststack.New[*ElementGroup]()\n\tglobalMap := make(ElementGroup)\n\ts.Push(&globalMap)\n\treturn &StateMachine{\n\t\tformula: formula + "*",\n\t\tstack:   s,\n\t}\n}\n\nfunc (sm *StateMachine) Len() int {\n\treturn len(sm.formula)\n}\n\nfunc (sm *StateMachine) PeakGroup() *ElementGroup {\n\tval, _ := sm.stack.Peek()\n\treturn val\n}\n\nfunc (sm *StateMachine) Process(i *int) {\n\tswitch sm.state {\n\tcase Open:\n\t\tsm.processOpen(i)\n\tcase Close:\n\t\tsm.processClose(i)\n\t}\n}\n\nfunc (sm *StateMachine) processOpen(i *int) {\n\tr := sm.formula[*i]\n\tcurGroup, _ := sm.stack.Peek()\n\tswitch {\n\tcase r == \'(\':\n\t\tcurGroup.Incr(sm.curEle, 1)\n\t\tsm.curEle = ""\n\t\tnewGroup := make(ElementGroup)\n\t\tsm.stack.Push(&newGroup)\n\tcase r == \')\':\n\t\tcurGroup.Incr(sm.curEle, 1)\n\t\tsm.curEle = ""\n\t\tsm.state = Close\n\tcase \'0\' <= r && r <= \'9\':\n\t\tnum := sm.scanNumber(i)\n\t\tcurGroup.Incr(sm.curEle, num)\n\t\tsm.curEle = ""\n\tdefault:\n\t\tcurGroup.Incr(sm.curEle, 1)\n\t\tsm.curEle = sm.scanElement(i)\n\t}\n}\n\nfunc (sm *StateMachine) processClose(i *int) {\n\tr := sm.formula[*i]\n\tcurGroup, _ := sm.stack.Pop()\n\tparentGroup, _ := sm.stack.Peek()\n\tsm.state = Open\n\tswitch {\n\tcase r == \'(\':\n\t\tparentGroup.MergeWithK(*curGroup, 1)\n\t\tnewGroup := make(ElementGroup)\n\t\tsm.stack.Push(&newGroup)\n\tcase r == \')\':\n\t\tparentGroup.MergeWithK(*curGroup, 1)\n\t\tsm.state = Close\n\tcase \'0\' <= r && r <= \'9\':\n\t\tnum := sm.scanNumber(i)\n\t\tparentGroup.MergeWithK(*curGroup, num)\n\tdefault:\n\t\tparentGroup.MergeWithK(*curGroup, 1)\n\t\tsm.curEle = sm.scanElement(i)\n\t}\n}\n\nfunc (sm *StateMachine) scanElement(i *int) string {\n\tj := *i + 1\n\tfor j < len(sm.formula) && \'a\' <= sm.formula[j] && sm.formula[j] <= \'z\' {\n\t\tj++\n\t}\n\tele := sm.formula[*i:j]\n\t*i = j - 1\n\treturn ele\n}\n\nfunc (sm *StateMachine) scanNumber(i *int) int {\n\tj := *i + 1\n\tfor j < len(sm.formula) && \'0\' <= sm.formula[j] && sm.formula[j] <= \'9\' {\n\t\tj++\n\t}\n\tnum, _ := strconv.Atoi(sm.formula[*i:j])\n\t*i = j - 1\n\treturn num\n}\n\ntype ElementGroup map[string]int\n\nfunc (m ElementGroup) Incr(e string, cnt int) {\n\tif len(e) > 0 {\n\t\tm[e] += cnt\n\t}\n}\n\nfunc (m ElementGroup) MergeWithK(n ElementGroup, k int) {\n\tfor key, v := range n {\n\t\tm[key] += v * k\n\t}\n}\n\nfunc (m ElementGroup) String() string {\n\ttype element struct {\n\t\tname string\n\t\tcnt  int\n\t}\n\telements := make([]*element, 0, len(m))\n\tfor k, v := range m {\n\t\telements = append(elements, &element{k, v})\n\t}\n\tsort.Slice(elements, func(i, j int) bool {\n\t\treturn elements[i].name < elements[j].name\n\t})\n\tsb := strings.Builder{}\n\tfor _, e := range elements {\n\t\tsb.WriteString(e.name)\n\t\tif e.cnt > 1 {\n\t\t\tsb.WriteString(fmt.Sprint(e.cnt))\n\t\t}\n\t}\n\treturn sb.String()\n}\n\n```
['Go']