You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
1.7 KiB
96 lines
1.7 KiB
package utils
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
"strconv"
|
|
)
|
|
|
|
type Stack []float64
|
|
|
|
func (s *Stack) IsEmpty() bool {
|
|
return len(*s) == 0
|
|
}
|
|
|
|
func (s *Stack) Push(op float64) {
|
|
*s = append(*s, op)
|
|
}
|
|
|
|
func (s *Stack) Pop() (float64, bool) {
|
|
if s.IsEmpty() {
|
|
return 0, false
|
|
}
|
|
index := len(*s) - 1
|
|
element := (*s)[index]
|
|
*s = (*s)[:index]
|
|
return element, true
|
|
}
|
|
|
|
func (s *Stack) PopTwo() (float64, float64, bool) {
|
|
if s.IsEmpty() || len(*s) < 2 {
|
|
return 0, 0, false
|
|
}
|
|
index := len(*s) - 1
|
|
b := (*s)[index]
|
|
a := (*s)[index-1]
|
|
*s = (*s)[:index-1]
|
|
return a, b, true
|
|
|
|
}
|
|
|
|
func (s *Stack) Top() float64 {
|
|
if s.IsEmpty() {
|
|
return 0
|
|
}
|
|
return (*s)[len(*s)-1]
|
|
}
|
|
|
|
func ParseRPN(args []string) (float64, error) {
|
|
s := Stack{}
|
|
for _, token := range args {
|
|
switch token {
|
|
case "+":
|
|
if a, b, ok := s.PopTwo(); ok {
|
|
s.Push(a + b)
|
|
} else {
|
|
return 0, fmt.Errorf("not enough operands on stack for +: %v", s)
|
|
}
|
|
case "-":
|
|
if a, b, ok := s.PopTwo(); ok {
|
|
s.Push(a - b)
|
|
} else {
|
|
return 0, fmt.Errorf("not enough operands on stack for -: %v", s)
|
|
}
|
|
case "*":
|
|
if a, b, ok := s.PopTwo(); ok {
|
|
s.Push(a * b)
|
|
} else {
|
|
return 0, fmt.Errorf("not enough operands on stack for *: %v", s)
|
|
}
|
|
case "/":
|
|
if a, b, ok := s.PopTwo(); ok {
|
|
s.Push(a / b)
|
|
} else {
|
|
return 0, fmt.Errorf("not enough operands on stack for /: %v", s)
|
|
}
|
|
case "%":
|
|
if a, b, ok := s.PopTwo(); ok {
|
|
s.Push(math.Mod(a, b))
|
|
} else {
|
|
return 0, fmt.Errorf("not enough operands on stack for %: %v", s)
|
|
}
|
|
default:
|
|
f, err := strconv.ParseFloat(token, 64)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
s.Push(f)
|
|
}
|
|
}
|
|
if res, ok := s.Pop(); ok {
|
|
return res, nil
|
|
}
|
|
return 0, errors.New("no result")
|
|
}
|