mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-05-18 19:13:27 +02:00
180 lines
4.1 KiB
Go
180 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/alexchao26/advent-of-code-go/cast"
|
|
"github.com/alexchao26/advent-of-code-go/util"
|
|
)
|
|
|
|
func main() {
|
|
var part int
|
|
flag.IntVar(&part, "part", 1, "part 1 or 2")
|
|
flag.Parse()
|
|
fmt.Println("Running part", part)
|
|
|
|
var ans int
|
|
if part == 1 {
|
|
ans = part1(util.ReadFile("./input.txt"))
|
|
} else {
|
|
ans = part2(util.ReadFile("./input.txt"))
|
|
}
|
|
fmt.Println("Output:", ans)
|
|
}
|
|
|
|
// 392
|
|
func part1(input string) int {
|
|
parsed := parseInput(input)
|
|
|
|
var total int
|
|
for _, line := range parsed {
|
|
// sum up this line, addressing things inside parens first...
|
|
total += doMaths(line, calcFlatSlicePart1)
|
|
}
|
|
|
|
return total
|
|
}
|
|
|
|
// ~1700 :(
|
|
func part2(input string) int {
|
|
lines := parseInput(input)
|
|
var total int
|
|
|
|
for _, line := range lines {
|
|
total += doMaths(line, calcFlatSlicePart2)
|
|
}
|
|
|
|
return total
|
|
}
|
|
|
|
func parseInput(input string) (ans [][]string) {
|
|
lines := strings.Split(input, "\n")
|
|
for _, l := range lines {
|
|
// I got lucky that they were all single digit numbers...
|
|
ans = append(ans, strings.Split(strings.ReplaceAll(l, " ", ""), ""))
|
|
}
|
|
return ans
|
|
}
|
|
|
|
func doMaths(input []string, flatteningFunc func([]string) string) int {
|
|
var stackOpenIndices []int
|
|
var stackFlattened []string
|
|
for i := 0; i < len(input); i++ {
|
|
// iterate through input, always append onto the flattened stack
|
|
// track open paren indices (in the flattened stack)
|
|
// on closing parens, use the top of the stackOpenIndices to flatten
|
|
// the most recent set of values/operations within parens, and replace
|
|
// their opening paren with the flattneed value
|
|
stackFlattened = append(stackFlattened, input[i])
|
|
switch input[i] {
|
|
case "(":
|
|
stackOpenIndices = append(stackOpenIndices, len(stackFlattened)-1)
|
|
case ")":
|
|
// on close parens, pass a section tohandleFlat
|
|
// then remove a bunch of shit from input,
|
|
openIndex := stackOpenIndices[len(stackOpenIndices)-1]
|
|
stackOpenIndices = stackOpenIndices[:len(stackOpenIndices)-1]
|
|
|
|
// do not include leading or trailing paren
|
|
sliToFlatten := stackFlattened[openIndex+1 : len(stackFlattened)-1]
|
|
stackFlattened[openIndex] = flatteningFunc(sliToFlatten)
|
|
|
|
// remove the values that were flattened off the top of the stack
|
|
stackFlattened = stackFlattened[:openIndex+1]
|
|
}
|
|
|
|
}
|
|
// slice should now be flat
|
|
return cast.ToInt(flatteningFunc(stackFlattened))
|
|
}
|
|
|
|
func calcFlatSlicePart1(input []string) string {
|
|
for _, v := range input {
|
|
if v == "(" || v == ")" {
|
|
panic(fmt.Sprintf("unexpected paren in flat input, %v", input))
|
|
}
|
|
}
|
|
|
|
result := cast.ToInt(input[0])
|
|
|
|
for i := range input {
|
|
if i+2 < len(input) {
|
|
switch input[i+1] {
|
|
case "+":
|
|
result += cast.ToInt(input[i+2])
|
|
case "*":
|
|
result *= cast.ToInt(input[i+2])
|
|
}
|
|
}
|
|
}
|
|
|
|
return cast.ToString(result)
|
|
}
|
|
|
|
func calcFlatSlicePart2(input []string) string {
|
|
for _, v := range input {
|
|
if v == "(" || v == ")" {
|
|
panic(fmt.Sprintf("unexpected paren in flat input, %v", input))
|
|
}
|
|
}
|
|
|
|
// handle all additions
|
|
for i := 1; i < len(input)-1; i++ {
|
|
if input[i] == "+" {
|
|
toLeft := input[i-1]
|
|
toRight := input[i+1]
|
|
if isNum(toLeft) && isNum(toRight) {
|
|
input[i-1] = addStrings(toLeft, toRight)
|
|
input = splice(input, i, 2)
|
|
i--
|
|
}
|
|
}
|
|
}
|
|
|
|
// then handle all multiplications
|
|
for i := 1; i < len(input)-1; i++ {
|
|
if input[i] == "*" {
|
|
toLeft := input[i-1]
|
|
toRight := input[i+1]
|
|
if isNum(toLeft) && isNum(toRight) {
|
|
input[i-1] = multiplyStrings(toLeft, toRight)
|
|
input = splice(input, i, 2)
|
|
i--
|
|
}
|
|
}
|
|
}
|
|
|
|
return input[0]
|
|
}
|
|
|
|
var numReg = regexp.MustCompile("[0-9]")
|
|
|
|
func isNum(str string) bool {
|
|
return numReg.MatchString(str)
|
|
}
|
|
|
|
func addStrings(strs ...string) string {
|
|
var sum int
|
|
for _, str := range strs {
|
|
sum += cast.ToInt(str)
|
|
}
|
|
return cast.ToString(sum)
|
|
}
|
|
func multiplyStrings(strs ...string) string {
|
|
sum := 1
|
|
for _, str := range strs {
|
|
sum *= cast.ToInt(str)
|
|
}
|
|
return cast.ToString(sum)
|
|
}
|
|
|
|
// removes a particular number of elements from the middle of the slice
|
|
func splice(sli []string, startIndex, items int) []string {
|
|
copy(sli[startIndex:], sli[startIndex+items:])
|
|
sli = sli[:len(sli)-items]
|
|
return sli
|
|
}
|