DEV Community

Discussion on: Daily Challenge #4 - Checkbook Balancing

Collapse
 
margo1993 profile image
margo1993
package utils

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

type CheckbookLine struct {
    checkNumber int
    category string
    checkAmount float64
}

func ProcessCheckbook(checkbook string) (string, error) {
    lines := strings.Split(checkbook, "\n")

    //Ignores all wrongly formatted lines
    checkbookLines := parseCheckbookLines(lines[1:])

    balance, e := findFloat(lines[0])
    if e != nil {
        return "", e
    }

    result := fmt.Sprintf("Original_Balance: %0.2f\n", balance)

    totalExpense := 0.0
    for _, checkbookLine := range checkbookLines {
        totalExpense += checkbookLine.checkAmount

        balance -= checkbookLine.checkAmount
        result += fmt.Sprintf("%d %s %0.2f Balance %0.2f\n", checkbookLine.checkNumber, checkbookLine.category, checkbookLine.checkAmount, balance)
    }

    result += fmt.Sprintf("Total expense %0.2f\n", totalExpense)
    checkbookLinesCount := len(checkbookLines)
    if checkbookLinesCount > 0 {
        result += fmt.Sprintf("Average expense %0.2f", totalExpense/float64(checkbookLinesCount))
    }

    return result, nil;
}

func parseCheckbookLines(lines []string) []CheckbookLine {
    var checkbookLines []CheckbookLine
    for _, line := range lines {

        fields := strings.Fields(line)
        if len(fields) < 3 {
            continue
        }

        checkNumber, e := findInteger(fields[0])
        if e != nil {
            continue
        }

        category := findClearString(fields[1])
        checkAmount, e := findFloat(fields[2])
        if e != nil {
            continue
        }

        checkbookLines = append(checkbookLines, CheckbookLine{checkNumber, category, checkAmount})
    }
    return checkbookLines
}

func findInteger(field string) (int, error) {
    r := regexp.MustCompile("[0-9]+")
    return strconv.Atoi(r.FindString(field))
}

func findClearString(field string) string {
    r := regexp.MustCompile("[A-Za-z]+")
    return r.FindString(field)
}

func findFloat(field string) (float64, error) {
    r := regexp.MustCompile("[0-9.-]+")
    return strconv.ParseFloat(r.FindString(field), 32)
}