@@ -4,44 +4,27 @@ import (
4
4
"fmt"
5
5
6
6
"github.com/believer/aoc-2024/utils/files"
7
+ "github.com/believer/aoc-2024/utils/grid"
7
8
)
8
9
9
10
// BFS to find plant regions and perimeters
10
11
// For part 2 find corners of areas which show how many sides it has
12
+ // Added a similar Grid/Point solution like I've used in my Rust solutions
13
+ // in previous years. Made things faster (one dimensional array of bytes) and cleaner!
11
14
func main () {
12
15
fmt .Println ("Part 1: " , part1 ("input.txt" ))
13
16
fmt .Println ("Part 2: " , part2 ("input.txt" ))
14
17
}
15
18
16
- type Location struct {
17
- r , c int
18
- }
19
-
20
- var directions = [][]int {
21
- {- 1 , 0 }, // Above
22
- {0 , 1 }, // Right
23
- {1 , 0 }, // Below
24
- {0 , - 1 }, // Left
25
- }
26
-
27
19
func part1 (name string ) int {
28
- plants := files .ReadLines (name )
29
- grid := map [Location ]byte {}
30
- visited := map [Location ]bool {}
31
-
32
- rows := len (plants )
33
- cols := len (plants [0 ])
20
+ lines := files .ReadLines (name )
21
+ plants := grid .New (lines )
22
+ visited := map [grid.Point ]bool {}
34
23
price := 0
35
24
36
- for r := range rows {
37
- for c := range cols {
38
- grid [Location {r , c }] = plants [r ][c ]
39
- }
40
- }
41
-
42
- for r := range rows {
43
- for c := range cols {
44
- area , perimeter := findPlantBed (grid , visited , Location {r , c })
25
+ for y := range plants .Height {
26
+ for x := range plants .Width {
27
+ area , perimeter := findPlantBed (plants , visited , grid.Point {X : x , Y : y })
45
28
price += len (area ) * perimeter
46
29
}
47
30
}
@@ -50,23 +33,14 @@ func part1(name string) int {
50
33
}
51
34
52
35
func part2 (name string ) int {
53
- plants := files .ReadLines (name )
54
- grid := map [Location ]byte {}
55
- visited := map [Location ]bool {}
56
-
57
- rows := len (plants )
58
- cols := len (plants [0 ])
36
+ lines := files .ReadLines (name )
37
+ plants := grid .New (lines )
38
+ visited := map [grid.Point ]bool {}
59
39
price := 0
60
40
61
- for r := range rows {
62
- for c := range cols {
63
- grid [Location {r , c }] = plants [r ][c ]
64
- }
65
- }
66
-
67
- for r := range rows {
68
- for c := range cols {
69
- area , _ := findPlantBed (grid , visited , Location {r , c })
41
+ for y := range plants .Height {
42
+ for x := range plants .Width {
43
+ area , _ := findPlantBed (plants , visited , grid.Point {X : x , Y : y })
70
44
price += len (area ) * findCorners (area )
71
45
}
72
46
}
@@ -75,32 +49,32 @@ func part2(name string) int {
75
49
}
76
50
77
51
// The number of corners shows how many sides we have
78
- func findCorners (area map [Location ]bool ) int {
52
+ func findCorners (area map [grid. Point ]bool ) int {
79
53
corners := 0
80
54
81
55
cornerChecks := []struct {
82
- offsets []Location
56
+ offsets []grid. Point
83
57
requiredStates []bool
84
58
}{
85
59
// Outer corners
86
- {[]Location {{ 0 , - 1 }, {- 1 , 0 }}, []bool {false , false }}, // Top left
87
- {[]Location {{ 0 , 1 }, {- 1 , 0 }}, []bool {false , false }}, // Top right
88
- {[]Location {{ 0 , - 1 }, {1 , 0 }}, []bool {false , false }}, // Bottom left
89
- {[]Location {{ 0 , 1 }, {1 , 0 }}, []bool {false , false }}, // Bottom right
60
+ {[]grid. Point {{ Y : 0 , X : - 1 }, {Y : - 1 , X : 0 }}, []bool {false , false }}, // Top left
61
+ {[]grid. Point {{ Y : 0 , X : 1 }, {Y : - 1 , X : 0 }}, []bool {false , false }}, // Top right
62
+ {[]grid. Point {{ Y : 0 , X : - 1 }, {Y : 1 , X : 0 }}, []bool {false , false }}, // Bottom left
63
+ {[]grid. Point {{ Y : 0 , X : 1 }, {Y : 1 , X : 0 }}, []bool {false , false }}, // Bottom right
90
64
91
65
// Inner corners
92
- {[]Location {{ - 1 , - 1 }, {- 1 , 0 }, {0 , - 1 }}, []bool {false , true , true }}, // Inside top left
93
- {[]Location {{ - 1 , 1 }, {- 1 , 0 }, {0 , 1 }}, []bool {false , true , true }}, // Inside top right
94
- {[]Location {{ 1 , - 1 }, {1 , 0 }, {0 , - 1 }}, []bool {false , true , true }}, // Inside bottom left
95
- {[]Location {{ 1 , 1 }, {1 , 0 }, {0 , 1 }}, []bool {false , true , true }}, // Inside bottom right
66
+ {[]grid. Point {{ Y : - 1 , X : - 1 }, {Y : - 1 , X : 0 }, {Y : 0 , X : - 1 }}, []bool {false , true , true }}, // Inside top left
67
+ {[]grid. Point {{ Y : - 1 , X : 1 }, {Y : - 1 , X : 0 }, {Y : 0 , X : 1 }}, []bool {false , true , true }}, // Inside top right
68
+ {[]grid. Point {{ Y : 1 , X : - 1 }, {Y : 1 , X : 0 }, {Y : 0 , X : - 1 }}, []bool {false , true , true }}, // Inside bottom left
69
+ {[]grid. Point {{ Y : 1 , X : 1 }, {Y : 1 , X : 0 }, {Y : 0 , X : 1 }}, []bool {false , true , true }}, // Inside bottom right
96
70
}
97
71
98
72
for a := range area {
99
73
for _ , check := range cornerChecks {
100
74
match := true
101
75
102
76
for i , offset := range check .offsets {
103
- neighbor := Location { a . r + offset . r , a . c + offset . c }
77
+ neighbor := a . Add ( offset )
104
78
105
79
if _ , ok := area [neighbor ]; ok != check .requiredStates [i ] {
106
80
match = false
@@ -117,10 +91,10 @@ func findCorners(area map[Location]bool) int {
117
91
return corners
118
92
}
119
93
120
- func findPlantBed (grid map [Location ]byte , visited map [Location ]bool , start Location ) (map [Location ]bool , int ) {
121
- queue := []Location {start }
94
+ func findPlantBed (g grid.Grid , visited map [grid.Point ]bool , start grid.Point ) (map [grid.Point ]bool , int ) {
95
+ queue := []grid.Point {start }
96
+ area := map [grid.Point ]bool {}
122
97
perimeter := 0
123
- area := map [Location ]bool {}
124
98
125
99
for len (queue ) > 0 {
126
100
current := queue [0 ]
@@ -130,7 +104,7 @@ func findPlantBed(grid map[Location]byte, visited map[Location]bool, start Locat
130
104
continue
131
105
}
132
106
133
- neighbors := getNeighbors (grid , current )
107
+ neighbors := getNeighbors (g , current )
134
108
perimeter += 4 - len (neighbors )
135
109
area [current ] = true
136
110
visited [current ] = true
@@ -143,13 +117,13 @@ func findPlantBed(grid map[Location]byte, visited map[Location]bool, start Locat
143
117
return area , perimeter
144
118
}
145
119
146
- func getNeighbors (grid map [ Location ] byte , current Location ) []Location {
147
- neighbors := []Location {}
120
+ func getNeighbors (g grid. Grid , current grid. Point ) []grid. Point {
121
+ neighbors := []grid. Point {}
148
122
149
- for _ , d := range directions {
150
- next := Location { current .r + d [ 0 ], current . c + d [ 1 ]}
123
+ for _ , d := range grid . CARDINALS {
124
+ next := current .Add ( d )
151
125
152
- if value , ok := grid [ next ] ; ok && value == grid [ current ] {
126
+ if value , ok := g . Contains ( next ) ; ok && value == g . Get ( current ) {
153
127
neighbors = append (neighbors , next )
154
128
}
155
129
}
0 commit comments