adventofcode/2023/day09/main.go

111 lines
2.2 KiB
Go

package main
import (
"fmt"
"strings"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
// 2185006187 is too high
// 1920491799 is too high
func main() {
inp := h.StdinToStringSlice()
solve(inp)
}
func solve(input []string) {
var p1result, p2result int
for i := range input {
s := NewSeq(i, input[i])
s.stabilize()
s.predict()
v2, v1 := s.value()
p1result += v1
p2result += v2
}
fmt.Println("# Part 1")
fmt.Println(p1result)
fmt.Println()
fmt.Println("# Part 2")
fmt.Println(p2result)
}
type Seq struct {
row int
history [][]int
}
func NewSeq(row int, input string) *Seq {
s := Seq{row: row}
pts := strings.Fields(input)
first := []int{}
for i := range pts {
first = append(first, h.Atoi(pts[i]))
}
s.history = append(s.history, first)
return &s
}
func (s *Seq) value() (int, int) {
return s.history[0][0], s.history[0][len(s.history[0])-1]
}
func (s *Seq) predict() {
s.history[len(s.history)-1] = append(s.history[len(s.history)-1], 0)
s.history[len(s.history)-1] = append([]int{0}, s.history[len(s.history)-1]...)
if len(s.history) > 1 {
for i := len(s.history) - 2; i >= 0; i-- {
nV := s.history[i][len(s.history[i])-1] + s.history[i+1][len(s.history[i+1])-1]
s.history[i] = append(s.history[i], nV)
// And now go backwards
pV := s.history[i][0] - s.history[i+1][0]
s.history[i] = append([]int{pV}, s.history[i]...)
}
}
}
func (s *Seq) stabilize() {
for !s.isStable() {
s.iterate()
}
}
func (s *Seq) iterate() {
idx := len(s.history) - 1
l := len(s.history[idx]) - 1
var next []int
for i := range s.history[idx] {
if i < l {
next = append(next, s.history[idx][i+1]-s.history[idx][i])
}
}
s.history = append(s.history, next)
}
func (s *Seq) isStable() bool {
for _, v := range s.history[len(s.history)-1] {
if v != 0 {
return false
}
}
return true
}
func (s Seq) String() string {
return fmt.Sprintf("MINE: Row %d Result: %d + %d = %d\n",
s.row,
s.history[0][len(s.history[0])-2],
s.history[1][len(s.history[1])-1],
s.history[0][len(s.history[0])-1])
}
func (s Seq) Detail() string {
var res string
for i := range s.history {
res = fmt.Sprintf("%s%v\n", res, s.history[i])
}
return res
}