Skip to content

Commit 84cdb92

Browse files
committed
Solution for 2023, day 21
1 parent 17b1f0b commit 84cdb92

File tree

4 files changed

+140
-0
lines changed

4 files changed

+140
-0
lines changed

2023/21/Makefile

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
main1:
2+
go build -o main1 main1.go common.go
3+
4+
main2:
5+
go build -o main2 main2.go common.go
6+
7+
.PHONY: run1 run2 clean
8+
9+
run1: main1
10+
./main1 <input
11+
12+
run2: main2
13+
./main2 <input
14+
15+
clean:
16+
rm -f main1 main2
17+

2023/21/common.go

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"os"
6+
"strings"
7+
)
8+
9+
type P struct{ x, y int }
10+
11+
type Map struct {
12+
m []string
13+
Start P
14+
Size int
15+
}
16+
17+
var Delta = []P{{-1, 0}, {0, 1}, {1, 0}, {0, -1}}
18+
19+
func (m Map) Get(p P) byte {
20+
var mod = P{
21+
x: ((p.x % m.Size) + m.Size) % m.Size,
22+
y: ((p.y % m.Size) + m.Size) % m.Size,
23+
}
24+
return m.m[mod.x][mod.y]
25+
}
26+
27+
func parse() Map {
28+
scanner := bufio.NewScanner(os.Stdin)
29+
var m Map
30+
var start P
31+
for r := 0; scanner.Scan(); r++ {
32+
line := scanner.Text()
33+
if idx := strings.IndexByte(line, 'S'); idx > -1 {
34+
start.x = r
35+
start.y = idx
36+
line = line[:idx] + "." + line[idx+1:]
37+
}
38+
m.m = append(m.m, line)
39+
}
40+
m.Size = len(m.m)
41+
m.Start = start
42+
return m
43+
}
44+
45+
func Reach(m Map, steps int) int {
46+
reachable := map[int]map[P]struct{}{}
47+
reachable[0] = map[P]struct{}{m.Start: {}}
48+
49+
for step := 1; step <= steps; step++ {
50+
newSteps := map[P]struct{}{}
51+
52+
for p := range reachable[step-1] {
53+
for _, delta := range Delta {
54+
next := P{p.x + delta.x, p.y + delta.y}
55+
if m.Get(next) == '#' {
56+
continue
57+
}
58+
newSteps[next] = struct{}{}
59+
}
60+
}
61+
62+
reachable[step] = newSteps
63+
delete(reachable, step-1)
64+
}
65+
66+
return len(reachable[steps])
67+
}

2023/21/main1.go

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package main
2+
3+
import "fmt"
4+
5+
func main() {
6+
m := parse()
7+
8+
fmt.Println(Reach(m, 64))
9+
}

2023/21/main2.go

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
6+
"gonum.org/v1/gonum/mat"
7+
)
8+
9+
const Steps = 26501365
10+
11+
func main() {
12+
m := parse()
13+
14+
// Find the 3 points necessary to generate the parabola coefficients
15+
16+
var points [3]P
17+
18+
for i, steps := range []int{
19+
m.Size / 2, // reach the border, fill one tile
20+
m.Size/2 + m.Size, // 5 tiles
21+
m.Size/2 + 2*m.Size, // 13 tiles
22+
} {
23+
cells := Reach(m, steps)
24+
points[i] = P{steps, cells}
25+
}
26+
27+
// Given these 3 points, we can find a,b,c such as
28+
// y = a*x^2 + b*x + c
29+
a, b, c := FindParabola(points)
30+
31+
fmt.Println(int(a*Steps*Steps + b*Steps + c))
32+
}
33+
34+
func FindParabola(p [3]P) (float64, float64, float64) {
35+
A := mat.NewDense(3, 3, []float64{
36+
float64(p[0].x * p[0].x), float64(p[0].x), 1,
37+
float64(p[1].x * p[1].x), float64(p[1].x), 1,
38+
float64(p[2].x * p[2].x), float64(p[2].x), 1,
39+
})
40+
41+
y := mat.NewVecDense(3, []float64{float64(p[0].y), float64(p[1].y), float64(p[2].y)})
42+
43+
var b mat.VecDense
44+
_ = b.SolveVec(A, y)
45+
46+
return b.AtVec(0), b.AtVec(1), b.AtVec(2)
47+
}

0 commit comments

Comments
 (0)