DEV Community

Discussion on: Daily Challenge #10 - Calculator

Collapse
 
margo1993 profile image
margo1993
package utils

import (
    "errors"
    "fmt"
    "math"
    "regexp"
    "strconv"
    "strings"
)

func evaluate(expression string) (float64, error) {
    supportedExpressions := []string{"/", "*", "+", "-"}

    expression = strings.Replace(expression, " ", "", len(expression) / 2)

    for _, e := range supportedExpressions {
        for moreExpressionsAvailable(expression, e) {
            firstExpression := findFirstExpression(expression, e)
            calculatedString, e := calculateString(firstExpression)

            if e != nil {
                return 0, e
            }

            expression = strings.Replace(expression, firstExpression, fmt.Sprintf("%0.2f", calculatedString), 1)
        }
    }
    result, e := strconv.ParseFloat(expression, 32)
    return math.Round(result * 100) / 100, e
}

func moreExpressionsAvailable(string string, e string) bool {
    r := regexp.MustCompile("\\" + e)
    return r.MatchString(string)
}

func findFirstExpression(expression string, operation string) string {
    r := regexp.MustCompile("[0-9.]+\\" + operation + "[0-9.]+")
    return r.FindString(expression)
}

func calculateString(expression string) (float64, error) {
    r := regexp.MustCompile("([0-9.]+)([/*+\\-])([0-9.]+)")

    submatches := r.FindStringSubmatch(expression)

    if len(submatches) < 3 {
        return 0, errors.New("not enought data")
    }

    num1, _ := strconv.ParseFloat(submatches[1], 32)
    numb2, _ := strconv.ParseFloat(submatches[3], 32)
    result, e := calculate(num1, numb2, submatches[2])
    return result, e
}

func calculate(num1 float64, num2 float64, operation string) (float64, error) {

    switch operation {
    case "*":
        return num1 * num2, nil
    case "/":
        return num1 / num2, nil
    case "+":
        return num1 + num2, nil
    case "-":
        return num1 - num2, nil
    }

    return 0, errors.New("Unsupported operator")
}