Search/ia-calc.go
partisan 57507756ec
Some checks failed
Run Integration Tests / test (push) Failing after 49s
Init Instant Answers
2025-06-25 23:23:33 +02:00

82 lines
2 KiB
Go

package main
import (
"fmt"
"regexp"
"strconv"
"strings"
)
// Enhanced math expression parser
func parseMathExpression(query string) (string, bool) {
// Clean and normalize the expression
query = strings.ReplaceAll(query, " ", "")
query = strings.ReplaceAll(query, ",", "")
// Regex to match valid math expressions
mathRegex := regexp.MustCompile(`^\d+(\.\d+)?([\+\-\*/\^]\d+(\.\d+)?)+$`)
if !mathRegex.MatchString(query) {
return "", false
}
// Operator precedence handling
operators := []struct {
symbol string
apply func(float64, float64) float64
}{
{"^", func(a, b float64) float64 {
result := 1.0
for i := 0; i < int(b); i++ {
result *= a
}
return result
}},
{"*", func(a, b float64) float64 { return a * b }},
{"/", func(a, b float64) float64 { return a / b }},
{"+", func(a, b float64) float64 { return a + b }},
{"-", func(a, b float64) float64 { return a - b }},
}
// Parse numbers and operators
var tokens []interface{}
current := ""
for _, char := range query {
if char >= '0' && char <= '9' || char == '.' {
current += string(char)
} else {
if current != "" {
num, _ := strconv.ParseFloat(current, 64)
tokens = append(tokens, num)
current = ""
}
tokens = append(tokens, string(char))
}
}
if current != "" {
num, _ := strconv.ParseFloat(current, 64)
tokens = append(tokens, num)
}
// Evaluate expression with operator precedence
for _, op := range operators {
for i := 1; i < len(tokens)-1; i += 2 {
if operator, ok := tokens[i].(string); ok && operator == op.symbol {
left := tokens[i-1].(float64)
right := tokens[i+1].(float64)
result := op.apply(left, right)
// Update tokens
tokens = append(tokens[:i-1], tokens[i+2:]...)
tokens = append(tokens[:i-1], append([]interface{}{result}, tokens[i-1:]...)...)
i -= 2 // Adjust index after modification
}
}
}
// Format result
result := tokens[0].(float64)
if result == float64(int(result)) {
return fmt.Sprintf("%d", int(result)), true
}
return fmt.Sprintf("%.2f", result), true
}