Skip to content

Commit cad3bd0

Browse files
committed
2023 day09 optimised
1 parent dc9cd1f commit cad3bd0

File tree

5 files changed

+89
-59
lines changed

5 files changed

+89
-59
lines changed

2023/day09/.bench

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"Lines":[{"Name":"Part 1","N":3436,"NsPerOp":354310,"AllocedBytesPerOp":0,"AllocsPerOp":0,"MBPerS":0,"Measured":1,"Ord":0},{"Name":"Part 2","N":3488,"NsPerOp":348238,"AllocedBytesPerOp":0,"AllocsPerOp":0,"MBPerS":0,"Measured":1,"Ord":0}],"Measured":1}
1+
{"Lines":[{"Name":"Part 1","N":70790,"NsPerOp":15110,"AllocedBytesPerOp":0,"AllocsPerOp":0,"MBPerS":0,"Measured":1,"Ord":0},{"Name":"Part 2","N":81368,"NsPerOp":14891,"AllocedBytesPerOp":0,"AllocsPerOp":0,"MBPerS":0,"Measured":1,"Ord":0}],"Measured":1}

2023/day09/main.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,77 @@ func main() {
2323
answer = doPartTwo(input)
2424
println(answer)
2525
}
26+
27+
var sequences [][]int
28+
29+
func parseInput(input string) {
30+
sequences = make([][]int, 0, 200)
31+
32+
i := 0
33+
for i < len(input) {
34+
if input[i] == '\n' || input[i] == '\r' {
35+
i++
36+
continue
37+
}
38+
39+
nums := make([]int, 0, 21)
40+
for i < len(input) && input[i] != '\n' {
41+
// Parse number (can be negative)
42+
negative := false
43+
if input[i] == '-' {
44+
negative = true
45+
i++
46+
}
47+
48+
num := 0
49+
for i < len(input) && input[i] >= '0' && input[i] <= '9' {
50+
num = num*10 + int(input[i]-'0')
51+
i++
52+
}
53+
if negative {
54+
num = -num
55+
}
56+
nums = append(nums, num)
57+
58+
// Skip space
59+
if i < len(input) && input[i] == ' ' {
60+
i++
61+
}
62+
}
63+
sequences = append(sequences, nums)
64+
}
65+
}
66+
67+
func extrapolate(nums []int) (int, int) {
68+
// Build difference pyramid and compute both extrapolations simultaneously
69+
n := len(nums)
70+
diffs := make([]int, n)
71+
copy(diffs, nums)
72+
73+
var nextVal, prevVal int
74+
sign := 1
75+
76+
for length := n; length > 1; length-- {
77+
// Add current rightmost value for part 1
78+
nextVal += diffs[length-1]
79+
80+
// Add current leftmost value for part 2 (alternating signs)
81+
prevVal += sign * diffs[0]
82+
sign = -sign
83+
84+
// Compute next level of differences
85+
allZero := true
86+
for i := 0; i < length-1; i++ {
87+
diffs[i] = diffs[i+1] - diffs[i]
88+
if diffs[i] != 0 {
89+
allZero = false
90+
}
91+
}
92+
93+
if allZero {
94+
break
95+
}
96+
}
97+
98+
return nextVal, prevVal
99+
}

2023/day09/main_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ package main
33
import "testing"
44

55
func BenchmarkPartOne(b *testing.B) {
6+
parseInput(input)
7+
b.ResetTimer()
68
for n := 0; n < b.N; n++ {
79
doPartOne(input)
810
}
911
}
1012

1113
func BenchmarkPartTwo(b *testing.B) {
14+
parseInput(input)
15+
b.ResetTimer()
1216
for n := 0; n < b.N; n++ {
1317
doPartTwo(input)
1418
}

2023/day09/part1.go

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,10 @@
11
package main
22

3-
import (
4-
"aocli/utils/reader"
5-
)
6-
73
func doPartOne(input string) int {
8-
numlist := reader.RowIntsByLine(input)
9-
var res int
10-
for _, nums := range numlist {
11-
extr := make([][]int, 0)
12-
extr = append(extr, nums)
13-
for {
14-
next := []int{}
15-
for i := 0; i < len(extr[len(extr)-1])-1; i++ {
16-
next = append(next, extr[len(extr)-1][i+1]-extr[len(extr)-1][i])
17-
}
18-
extr = append(extr, next)
19-
allzero := true
20-
for _, v := range next {
21-
if v != 0 {
22-
allzero = false
23-
}
24-
}
25-
if allzero {
26-
break
27-
}
28-
}
29-
for i := len(extr) - 2; i >= 0; i-- {
30-
res += extr[i][len(extr[i])-1]
31-
}
4+
var sum int
5+
for _, nums := range sequences {
6+
next, _ := extrapolate(nums)
7+
sum += next
328
}
33-
return res
9+
return sum
3410
}

2023/day09/part2.go

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,10 @@
11
package main
22

3-
import "aocli/utils/reader"
4-
53
func doPartTwo(input string) int {
6-
numlist := reader.RowIntsByLine(input)
7-
var res int
8-
for _, nums := range numlist {
9-
extr := make([][]int, 0)
10-
extr = append(extr, nums)
11-
var R int
12-
for {
13-
next := []int{}
14-
for i := 0; i < len(extr[len(extr)-1])-1; i++ {
15-
next = append(next, extr[len(extr)-1][i+1]-extr[len(extr)-1][i])
16-
}
17-
extr = append(extr, next)
18-
allzero := true
19-
for _, v := range next {
20-
if v != 0 {
21-
allzero = false
22-
}
23-
}
24-
if allzero {
25-
break
26-
}
27-
}
28-
for i := len(extr) - 2; i >= 0; i-- {
29-
R = extr[i][0] - R
30-
}
31-
res += R
4+
var sum int
5+
for _, nums := range sequences {
6+
_, prev := extrapolate(nums)
7+
sum += prev
328
}
33-
return res
9+
return sum
3410
}

0 commit comments

Comments
 (0)