package main import ( "fmt" "regexp" "strings" h "git.bullercodeworks.com/brian/adventofcode/helpers" ) var rgx = regexp.MustCompile(`\([0-9\*\+ ]*\)`) const ( LtoR = iota AthenM ) func main() { fmt.Println("# Day 18") fmt.Println() inp := h.StdinToStringSlice() fmt.Println("## Part1\nAnswer:", sum(inp, LtoR)) fmt.Println("## Part2\nAnswer:", sum(inp, AthenM)) } func sum(inp []string, algo int) int { var ret int for k := range inp { ret = ret + solve(inp[k], algo) } return ret } func solve(inp string, algo int) int { var total int rs := rgx.FindString(inp) if rs == "" { // no parentheticals total = evaluateLine(inp, algo) } else { for rs != "" { repl := evaluateLine(rs[1:len(rs)-1], algo) inp = strings.Replace(inp, rs, h.Itoa(repl), -1) rs = rgx.FindString(inp) } total = evaluateLine(inp, algo) } return total } func evaluateLine(inp string, algo int) int { switch algo { case LtoR: return evaluateLineLtoR(inp) case AthenM: return evaluateLineAthenM(inp) } return 0 } func evaluateLineLtoR(inp string) int { var cnt, total int var op string // No parentheticals pts := strings.Split(inp, " ") for k := range pts { switch pts[k] { case "*", "+": op = pts[k] default: if cnt == 0 { total = h.Atoi(pts[k]) cnt++ } else { if op == "+" { total = total + h.Atoi(pts[k]) } else { total = total * h.Atoi(pts[k]) } } } } return total } func evaluateLineAthenM(inp string) int { // First solve all addition inp = evaluateLineAddition(inp) inp = evaluateLineMultiplication(inp) return h.Atoi(inp) } func evaluateLineAddition(inp string) string { var newPts []string for strings.Contains(inp, "+") { pts := strings.Split(inp, " ") for k := 0; k < len(pts); k++ { if pts[k] == "+" { newPts = pts[:k-1] newPts = append(newPts, h.Itoa(h.Atoi(pts[k-1])+h.Atoi(pts[k+1]))) newPts = append(newPts, pts[k+2:]...) inp = strings.Join(newPts, " ") break } } } return inp } func evaluateLineMultiplication(inp string) string { var newPts []string for strings.Contains(inp, "*") { pts := strings.Split(inp, " ") for k := 0; k < len(pts); k++ { if pts[k] == "*" { newPts = pts[:k-1] newPts = append(newPts, h.Itoa(h.Atoi(pts[k-1])*h.Atoi(pts[k+1]))) newPts = append(newPts, pts[k+2:]...) inp = strings.Join(newPts, " ") break } } } return inp } type Token struct { SubTokens []Token }