adventofcode/2020/day18/main.go
2020-12-18 13:09:31 -06:00

130 lines
2.4 KiB
Go

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
}