-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path12p1.go
151 lines (125 loc) · 2.92 KB
/
12p1.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package main
import (
"fmt"
"aoc2022/utils"
)
type node struct {
value int
letter string
visited bool
start bool
end bool
movesFromStart int
}
type nodeCoordinate struct {
x int
y int
}
func D12P1() {
lines := utils.ReadLines("./inputs/12.txt")
hills := parseHills(lines)
queue := []nodeCoordinate{}
// Append start node to queue
start := findStart(hills, false)
value, exists := hills[start]
if exists {
value.movesFromStart = 0
}
queue = append(queue, start)
for queue != nil {
if hills[queue[0]].visited {
queue = queue[1:]
continue
}
if hills[queue[0]].end {
fmt.Printf("Reached end in %d moves\n", hills[queue[0]].movesFromStart)
break
}
neighbours := findNeighbours(&hills, queue[0], false)
for _, n := range neighbours {
value, exists := hills[n]
if exists {
value.movesFromStart = updateMovesFromStart(value, hills[queue[0]])
hills[n] = value
}
queue = append(queue, n)
}
value, exists := hills[queue[0]]
if exists {
value.visited = true
hills[queue[0]] = value
}
queue = queue[1:]
}
}
func parseHills(lines []string) map[nodeCoordinate]node {
hills := map[nodeCoordinate]node{}
maxIntValue := int(^uint(0) >> 1)
for y, line := range lines {
for x, char := range line {
movesFromStart := maxIntValue
start, end := false, false
if string(char) == "S" {
char = 'a'
start = true
}
if string(char) == "E" {
char = 'z'
end = true
}
hills[nodeCoordinate{x, y}] = node{
value: int(char),
letter: string(char),
visited: false,
start: start,
end: end,
movesFromStart: movesFromStart,
}
}
}
return hills
}
func findStart(hills map[nodeCoordinate]node, reverse bool) nodeCoordinate {
for coordinate, hill := range hills {
if hill.start && !reverse {
return coordinate
}
if hill.end && reverse {
return coordinate
}
}
return nodeCoordinate{}
}
func findNeighbours(
hills *map[nodeCoordinate]node,
coordinate nodeCoordinate,
reverse bool,
) []nodeCoordinate {
neighbours := []nodeCoordinate{}
posibleNeighbours := []nodeCoordinate{
{coordinate.x + 1, coordinate.y},
{coordinate.x - 1, coordinate.y},
{coordinate.x, coordinate.y + 1},
{coordinate.x, coordinate.y - 1},
}
currentHillValue := (*hills)[coordinate].value
for _, possibleNeighbour := range posibleNeighbours {
value, exists := (*hills)[possibleNeighbour]
if exists && value.value-currentHillValue > 1 && !reverse {
continue
}
if exists && currentHillValue-value.value > 1 && reverse {
continue
}
if exists && !value.visited {
neighbours = append(neighbours, possibleNeighbour)
}
}
return neighbours
}
func updateMovesFromStart(hill node, currentPosition node) int {
if hill.movesFromStart > currentPosition.movesFromStart+1 {
return currentPosition.movesFromStart + 1
}
return hill.movesFromStart
}