Add solution for day 9 part 1
parent
756fa3b52a
commit
587d832294
|
@ -0,0 +1,100 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 && len(os.Args) != 3 {
|
||||
fmt.Fprintf(os.Stderr, "Usage: %s inputfile\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
inputFilename := os.Args[1]
|
||||
inputFile, err := os.Open(inputFilename)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("could not open input file: %s", err))
|
||||
}
|
||||
|
||||
defer inputFile.Close()
|
||||
|
||||
inputBytes, err := io.ReadAll(inputFile)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("could not read input file: %s", err))
|
||||
}
|
||||
|
||||
input := strings.TrimSpace(string(inputBytes))
|
||||
inputLines := strings.Split(input, "\n")
|
||||
histories, err := parseHistories(inputLines)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to parse histories: %s", err))
|
||||
}
|
||||
|
||||
fmt.Printf("Part 1: %d\n", part1(histories))
|
||||
}
|
||||
|
||||
func part1(histories [][]int) int {
|
||||
total := 0
|
||||
for _, history := range histories {
|
||||
total += predictNextValue(history)
|
||||
}
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
// predictNextValue calculates the next item in the sequence by using the nth differences
|
||||
func predictNextValue(history []int) int {
|
||||
if allEqual(history, 0) {
|
||||
return 0
|
||||
}
|
||||
|
||||
differences := make([]int, len(history)-1)
|
||||
for i := range history[1:] {
|
||||
differences[i] = history[i+1] - history[i]
|
||||
}
|
||||
|
||||
return history[len(history)-1] + predictNextValue(differences)
|
||||
}
|
||||
|
||||
func allEqual[T comparable, S ~[]T](values S, shouldEqual T) bool {
|
||||
for _, value := range values {
|
||||
if value != shouldEqual {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func parseHistories(lines []string) ([][]int, error) {
|
||||
histories := make([][]int, len(lines))
|
||||
for i, line := range lines {
|
||||
history, err := parseHistory(line)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse history %d: %s", i, err)
|
||||
}
|
||||
|
||||
histories[i] = history
|
||||
}
|
||||
|
||||
return histories, nil
|
||||
}
|
||||
|
||||
func parseHistory(line string) ([]int, error) {
|
||||
rawNums := strings.Split(line, " ")
|
||||
history := make([]int, len(rawNums))
|
||||
for i, rawNum := range rawNums {
|
||||
n, err := strconv.Atoi(rawNum)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse item %d: %w", i, err)
|
||||
}
|
||||
|
||||
history[i] = n
|
||||
}
|
||||
|
||||
return history, nil
|
||||
}
|
Loading…
Reference in New Issue