Превышен лимит времени исполнения в строчном калькуляторе на Go
Вот условие задачи:
Реализовать функцию
func Calc(expression string) (float64, error)
, гдеexpression
— строка-выражение, состоящая из односимвольных идентификаторов и знаков арифметических действий.Входящие данные — цифры (рациональные), операции
+
,-
,*
,/
и операции приоритезации(
и)
.В случае ошибки записи выражения функция должна выдать ошибку.
Вот код:
package main
import (
"errors"
"fmt"
"strconv"
"unicode"
)
func Calc(expression string) (float64, error) {
priority := map[rune]int{'+': 1, '-': 1, '*': 2, '/': 2}
var num []float64
var operator []rune
var hasNumber bool
for _, ch := range expression {
if unicode.IsDigit(ch) {
hasNumber = true
}
}
if !hasNumber {
return 0, errors.New("no number")
}
if len(expression) == 0 {
return 0, errors.New("empty expression")
}
check := rune(expression[len(expression)-1])
if !unicode.IsDigit(check) && check != ')' {
return 0, errors.New("invalid, last char is not digits or closing bracket")
}
applyOperator := func(a, b float64, op rune) float64 {
switch op {
case '+':
return a + b
case '-':
return a - b
case '*':
return a * b
case '/':
if b == 0 {
panic("division by zero")
}
return a / b
default:
return 0
}
}
calculate := func() {
if len(operator) == 0 || len(num) < 2 {
return
}
b := num[len(num)-1]
a := num[len(num)-2]
op := operator[len(operator)-1]
num = num[:len(num)-2]
operator = operator[:len(operator)-1]
result := applyOperator(a, b, op)
num = append(num, result)
}
for i := 0; i < len(expression); i++ {
ch := rune(expression[i])
if unicode.IsDigit(ch) || ch == '.' {
start := i
for i < len(expression) && (unicode.IsDigit(rune(expression[i])) || expression[i] == '.') {
i++
}
numer, err := strconv.ParseFloat(expression[start:i], 64)
if err != nil {
return 0, fmt.Errorf("failed to parse number: %v", err)
}
num = append(num, numer)
i--
} else if ch == '+' || ch == '-' {
if i == 0 || expression[i-1] == '(' || len(operator) > 0 && operator[len(operator)-1] == '(' {
num = append(num, 0)
}
for len(operator) > 0 && priority[operator[len(operator)-1]] >= priority[ch] {
calculate()
}
operator = append(operator, ch)
} else if ch == '*' || ch == '/' {
for len(operator) > 0 && priority[operator[len(operator)-1]] >= priority[ch] {
calculate()
}
operator = append(operator, ch)
} else if ch == '(' {
operator = append(operator, ch)
} else if ch == ')' {
for len(operator) > 0 && operator[len(operator)-1] != '(' {
calculate()
}
if len(operator) == 0 {
return 0, errors.New("mismatched parentheses")
}
operator = operator[:len(operator)-1]
} else if !unicode.IsSpace(ch) {
return 0, errors.New("invalid character")
}
}
for len(operator) > 0 {
calculate()
}
if len(num) == 1 {
return num[0], nil
}
return 0, errors.New("invalid expression")
}
Этот строчный калькулятор при проверки тестовой системой выдаёт ошибку:
Превышен лимит времени исполнения программы
Программа при каком-то случае входит в бесконечный цикл. Я думаю, что не обработан какой-то из случаев ошибки.
Реализован этот калькулятор с помощью двух стеков: в одном операции, в другом числа.
Принцип работы взял из видео.