Files
advent-of-code-go/2018/day12/main.go
T
2020-12-01 17:05:34 -05:00

150 lines
3.5 KiB
Go

package main
import (
"flag"
"fmt"
"log"
"strings"
"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)
if part == 1 {
ans := part1(util.ReadFile("./input.txt"))
fmt.Println("Output:", ans)
} else {
ans := part2(util.ReadFile("./input.txt"))
fmt.Println("Output:", ans)
}
}
func part1(input string) int {
initialZeroIndex := 25 // lazy placement of empty pots to left and right of inputs
state, changesMap := parseInputs(input, initialZeroIndex)
// fmt.Printf("%d\t%v\n", 0, state)
for i := 0; i < 20; i++ {
state = step(state, changesMap)
// fmt.Printf("%d\t%v\n", i+1, state)
}
ans := sumOfPotNumbers(state, initialZeroIndex)
return ans
}
func part2(input string) int {
initialZeroIndex := 300 // lazy placement of empty pots to left and right of inputs
state, changesMap := parseInputs(input, initialZeroIndex)
patterns := map[string]int{}
sums := []int{sumOfPotNumbers(state, initialZeroIndex)}
var patternIndices [2]int
for gens := 1; gens < initialZeroIndex-100; gens++ {
state = step(state, changesMap)
// fmt.Printf("%d\t%v\n", gens, state)
currentSum := sumOfPotNumbers(state, initialZeroIndex)
sums = append(sums, currentSum)
trimmedPattern := strings.Trim(stringify(state), ".")
// fmt.Printf("%d\t%s\n", gens, trimmedPattern)
if lastIndex, ok := patterns[trimmedPattern]; ok {
patternIndices = [2]int{lastIndex, gens}
break // break once a pattern is found
} else {
// store pattern to index so the pattern frequency can be found
patterns[trimmedPattern] = gens
}
}
// calc to 50000000000
// find the frequency and the sum's diff, then add that diff * number of generations left
freq := patternIndices[1] - patternIndices[0]
patternDiff := sums[patternIndices[1]] - sums[patternIndices[0]]
if freq != 1 {
log.Fatal("Pattern frequency is assumed to be 1, part2() needs to be updated to handle != 1 cases")
}
fiveBillion := 50000000000
ans := sums[patternIndices[1]] + (fiveBillion-patternIndices[1])*patternDiff
return ans
}
func parseInputs(input string, initialZeroIndex int) (state []string, changesMap map[string]string) {
lines := strings.Split(input, "\n")
first := strings.Split(lines[0], "state: ")
// increment it by 3 to account for empty nodes at start
for i := 0; i < initialZeroIndex; i++ {
state = append(state, ".")
}
for _, val := range first[1] {
state = append(state, string(val))
}
// add 3 onto end also
for i := 0; i < initialZeroIndex; i++ {
state = append(state, ".")
}
changesMap = make(map[string]string)
for i := 2; i < len(lines); i++ {
line := lines[i]
if line != "" {
splitStep := strings.Split(line, " => ")
changesMap[splitStep[0]] = splitStep[1]
}
}
return state, changesMap
}
func step(state []string, changesMap map[string]string) (nextState []string) {
for i := range state {
fiveStr := ""
for index := i - 2; index >= 0 && index < len(state) && len(fiveStr) < 5; index++ {
fiveStr += state[index]
}
if v, ok := changesMap[fiveStr]; ok {
nextState = append(nextState, v)
} else {
// missing case should only apply to examples or len < 5
nextState = append(nextState, ".")
}
}
return nextState
}
func sumOfPotNumbers(state []string, zeroIndex int) int {
ans := 0
for i, v := range state {
if v == "#" {
ans += i - zeroIndex
}
}
return ans
}
func stringify(state []string) string {
ans := ""
for _, v := range state {
ans += v
}
return ans
}