Skip to content

Commit 00b1595

Browse files
committed
[2024] Solution for Day 18
1 parent 6509448 commit 00b1595

File tree

3 files changed

+187
-1
lines changed

3 files changed

+187
-1
lines changed

2024/day18/main.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
8+
"github.com/kfarnung/advent-of-code/2024/lib"
9+
)
10+
11+
type point struct {
12+
x, y int
13+
}
14+
15+
type mazeState struct {
16+
position point
17+
stepCount int
18+
}
19+
20+
func part1(input string, dimension, count int) int64 {
21+
points, err := parseInput(input)
22+
if err != nil {
23+
log.Fatal(err)
24+
}
25+
26+
grid := initializeGrid(dimension)
27+
corruptGrid(grid, points, count)
28+
29+
return int64(findShortestPath(grid, point{0, 0}, point{dimension, dimension}))
30+
}
31+
32+
func part2(input string, dimension int) string {
33+
points, err := parseInput(input)
34+
if err != nil {
35+
log.Fatal(err)
36+
}
37+
38+
grid := initializeGrid(dimension)
39+
40+
for _, p := range points {
41+
grid[p.y][p.x] = '#'
42+
43+
if findShortestPath(grid, point{0, 0}, point{dimension, dimension}) == 0 {
44+
return fmt.Sprintf("%d,%d", p.x, p.y)
45+
}
46+
}
47+
48+
log.Fatal("No solution found")
49+
return ""
50+
}
51+
52+
func findShortestPath(grid [][]rune, start, end point) int {
53+
queue := []mazeState{{start, 0}}
54+
steps := make(map[point]int)
55+
56+
for len(queue) > 0 {
57+
current := queue[0]
58+
queue = queue[1:]
59+
60+
if stepCount, ok := steps[current.position]; ok && stepCount <= current.stepCount {
61+
continue
62+
}
63+
64+
steps[current.position] = current.stepCount
65+
66+
if current.position == end {
67+
break
68+
}
69+
70+
for _, direction := range []point{{0, 1}, {0, -1}, {1, 0}, {-1, 0}} {
71+
next := point{current.position.x + direction.x, current.position.y + direction.y}
72+
if next.y >= 0 && next.y < len(grid) && next.x >= 0 && next.x < len(grid[next.y]) && grid[next.y][next.x] == '.' {
73+
queue = append(queue, mazeState{next, current.stepCount + 1})
74+
}
75+
}
76+
}
77+
78+
return steps[end]
79+
}
80+
81+
func corruptGrid(grid [][]rune, points []point, count int) {
82+
for i := 0; i < count; i++ {
83+
grid[points[i].y][points[i].x] = '#'
84+
}
85+
}
86+
87+
func initializeGrid(dimension int) [][]rune {
88+
grid := make([][]rune, dimension+1)
89+
for i := range grid {
90+
grid[i] = make([]rune, dimension+1)
91+
for j := range grid[i] {
92+
grid[i][j] = '.'
93+
}
94+
}
95+
96+
return grid
97+
}
98+
99+
func parseInput(input string) ([]point, error) {
100+
var points []point
101+
for _, line := range lib.SplitLines(input) {
102+
if line == "" {
103+
continue
104+
}
105+
106+
var x, y int
107+
_, err := fmt.Sscanf(line, "%d,%d", &x, &y)
108+
if err != nil {
109+
return nil, err
110+
}
111+
points = append(points, point{x, y})
112+
}
113+
114+
return points, nil
115+
}
116+
117+
func main() {
118+
name := os.Args[1]
119+
content, err := lib.LoadFileContent(name)
120+
if err != nil {
121+
log.Fatal(err)
122+
}
123+
124+
fmt.Printf("Part 1: %d\n", part1(content, 70, 1024))
125+
fmt.Printf("Part 2: %s\n", part2(content, 70))
126+
}

2024/day18/main_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package main
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/kfarnung/advent-of-code/2024/lib"
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
var input = strings.Join([]string{
12+
"5,4",
13+
"4,2",
14+
"4,5",
15+
"3,0",
16+
"2,1",
17+
"6,3",
18+
"2,4",
19+
"1,5",
20+
"0,6",
21+
"3,3",
22+
"2,6",
23+
"5,1",
24+
"1,2",
25+
"5,5",
26+
"2,5",
27+
"6,5",
28+
"1,4",
29+
"0,4",
30+
"6,4",
31+
"1,1",
32+
"6,1",
33+
"1,0",
34+
"0,5",
35+
"1,6",
36+
"2,0",
37+
"",
38+
}, "\n")
39+
40+
func TestPart1(t *testing.T) {
41+
assert.Equal(t, int64(22), part1(input, 6, 12))
42+
43+
inputContent, err := lib.GetInputContent()
44+
if err != nil {
45+
t.Fatal(err)
46+
}
47+
48+
assert.Equal(t, int64(330), part1(inputContent, 70, 1024))
49+
}
50+
51+
func TestPart2(t *testing.T) {
52+
assert.Equal(t, "6,1", part2(input, 6))
53+
54+
inputContent, err := lib.GetInputContent()
55+
if err != nil {
56+
t.Fatal(err)
57+
}
58+
59+
assert.Equal(t, "10,38", part2(inputContent, 70))
60+
}

private

0 commit comments

Comments
 (0)