import ( "strconv" "strings" ) func calculate(s string) int { none := struct{}{} opsSet := map[byte]struct{}{'+': none, '-': none, '*': none, '/': none} ops := make([]byte, 0) nums := make([]int, 0) prev := -1 for i := range s { if _, ok := opsSet[s[i]]; ok { num, _ := strconv.Atoi(strings.Trim(s[prev+1:i], " ")) // Atoi should trim all spaces of string mulOrDiv(&nums, &ops, &num) nums = append(nums, num) ops = append(ops, s[i]) prev = i } } num, _ := strconv.Atoi(strings.Trim(s[prev+1:], " ")) mulOrDiv(&nums, &ops, &num) nums = append(nums, num) for left, right := 0, len(nums)-1; left < right; left, right = left+1, right-1 { nums[left], nums[right] = nums[right], nums[left] } // Reverse nums and ops for left, right := 0, len(ops)-1; left < right; left, right = left+1, right-1 { ops[left], ops[right] = ops[right], ops[left] } for l1, l2 := len(nums), len(ops); l1 != 1; l1, l2 = l1-1, l2-1 { op := ops[l2-1] ops = ops[:l2-1] n1, n2 := nums[l1-2], nums[l1-1] nums = nums[:l1-2] switch op { case '+': nums = append(nums, n2+n1) case '-': nums = append(nums, n2-n1) } } return nums[0] } func mulOrDiv(nums *[]int, ops *[]byte, num *int) { if l := len(*ops); l != 0 && ((*ops)[l-1] == '*' || (*ops)[l-1] == '/') { n := (*nums)[len(*nums)-1] *nums = (*nums)[:len(*nums)-1] switch (*ops)[l-1] { case '*': *num = n * (*num) case '/': *num = n / (*num) } *ops = (*ops)[:l-1] } }