diff --git a/pkg/rpn/rpn.go b/pkg/rpn/rpn.go deleted file mode 100644 index db39f5d..0000000 --- a/pkg/rpn/rpn.go +++ /dev/null @@ -1,156 +0,0 @@ -package utils - -import ( - "fmt" - "strconv" - "strings" -) - -type Operator struct { - Token string - Precedence int - Association string -} - -func (o Operator) HasHigherPrecedence(t Operator) bool { - return o.Precedence < t.Precedence // lower number is higher precedence -} - -func (o Operator) HasEqualPrecedence(t Operator) bool { - return o.Precedence == t.Precedence -} - -func (o Operator) IsLeftAssociative() bool { - return o.Association == "left" -} - -var operators = map[string]Operator{ - "+": Operator{ - Token: "+", - Precedence: 4, - Association: "left", - }, - "-": Operator{ - Token: "-", - Precedence: 4, - Association: "left", - }, - "*": Operator{ - Token: "*", - Precedence: 3, - Association: "left", - }, - "/": Operator{ - Token: "/", - Precedence: 3, - Association: "left", - }, - "%": Operator{ - Token: "%", - Precedence: 3, - Association: "left", - }, - "(": Operator{ - Token: "(", - Precedence: 1, - Association: "left", - }, - ")": Operator{ - Token: ")", - Precedence: 1, - Association: "left", - }, -} - -type Stack []Operator - -func (s *Stack) IsEmpty() bool { - return len(*s) == 0 -} - -func (s *Stack) Push(op Operator) { - *s = append(*s, op) -} - -func (s *Stack) Pop() (Operator, bool) { - if s.IsEmpty() { - return Operator{}, false - } - index := len(*s) - 1 - element := (*s)[index] - *s = (*s)[:index] - return element, true -} - -func (s *Stack) Top() Operator { - if s.IsEmpty() { - return Operator{} - } - return (*s)[len(*s)-1] -} - -func GenerateRPN(tokens []string) (string, error) { - output := "" - s := Stack{} - for _, token := range tokens { - err := processToken(token, &s, &output) - if err != nil { - return "", err - } - } - for !s.IsEmpty() { - ele, _ := s.Pop() - output += " " + ele.Token - } - - return strings.TrimSpace(output), nil -} - -func processToken(t string, s *Stack, o *string) error { - if _, err := strconv.Atoi(t); err == nil { - *o += " " + t - return nil - } else if op, ok := operators[t]; ok { - if op.Token == "(" { - s.Push(op) - } else if op.Token == ")" { - if s.IsEmpty() { - return fmt.Errorf("mismatched parentheses") - } - for s.Top().Token != "(" { - if ele, ok := s.Pop(); ok { - *o += " " + ele.Token - } else { - return fmt.Errorf("mismatched parentheses") - } - if s.IsEmpty() { - break - } - } - s.Pop() // Pop and discard the ( - } else if !s.IsEmpty() { - for { - if (s.Top().HasHigherPrecedence(op) || - (s.Top().HasEqualPrecedence(op) && - op.IsLeftAssociative())) && - s.Top().Token != "(" { - if ele, ok := s.Pop(); ok { - *o += " " + ele.Token - if s.IsEmpty() { - break - } - continue - } else { - break - } - } - break - } - s.Push(op) - } else { - s.Push(op) - } - return nil - } - return fmt.Errorf("invalid character %s", t) -} diff --git a/pkg/rpn/rpnParser.go b/pkg/rpn/rpnParser.go deleted file mode 100644 index 7f9dff9..0000000 --- a/pkg/rpn/rpnParser.go +++ /dev/null @@ -1,95 +0,0 @@ -package utils - -import ( - "errors" - "fmt" - "math" - "strconv" -) - -type FStack []float64 - -func (s *FStack) IsEmpty() bool { - return len(*s) == 0 -} - -func (s *FStack) Push(op float64) { - *s = append(*s, op) -} - -func (s *FStack) Pop() (float64, bool) { - if s.IsEmpty() { - return 0, false - } - index := len(*s) - 1 - element := (*s)[index] - *s = (*s)[:index] - return element, true -} - -func (s *FStack) 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 *FStack) Top() float64 { - if s.IsEmpty() { - return 0 - } - return (*s)[len(*s)-1] -} - -func ParseRPN(args []string) (float64, error) { - s := FStack{} - 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") -}