-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathday18.go
97 lines (84 loc) · 2.04 KB
/
day18.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
package main
import (
"flag"
"fmt"
"io/ioutil"
"strconv"
"strings"
"github.com/lizthegrey/adventofcode/2022/heapq"
)
var inputFile = flag.String("inputFile", "inputs/day18.input", "Relative file path to use as input.")
type coord struct {
x, y int
}
func (c coord) add(o coord) coord {
return coord{c.x + o.x, c.y + o.y}
}
const maxCoord = 70
func main() {
flag.Parse()
bytes, err := ioutil.ReadFile(*inputFile)
if err != nil {
return
}
contents := string(bytes)
split := strings.Split(contents, "\n")
var incoming []coord
for _, s := range split[:len(split)-1] {
parts := strings.Split(s, ",")
x, _ := strconv.Atoi(parts[0])
y, _ := strconv.Atoi(parts[1])
incoming = append(incoming, coord{x, y})
}
impassable := make(map[coord]bool)
for i, loc := range incoming {
impassable[loc] = true
if i < 1024 {
continue
}
steps := aStar(impassable, coord{0, 0}, coord{maxCoord, maxCoord})
if i == 1024 {
fmt.Println(steps)
}
if steps == -1 {
fmt.Printf("%d,%d\n", loc.x, loc.y)
return
}
}
}
func aStar(impassable map[coord]bool, start, target coord) int {
gScore := map[coord]int{
start: 0,
}
workList := heapq.New[coord]()
workList.Upsert(start, start.heuristic(target))
for workList.Len() != 0 {
// Pop the current node off the worklist.
current := workList.PopSafe()
if current == target {
return gScore[current]
}
for _, n := range current.iterate(impassable) {
proposedScore := gScore[current] + 1
if previousScore, ok := gScore[n]; !ok || proposedScore < previousScore {
gScore[n] = proposedScore
workList.Upsert(n, proposedScore+n.heuristic(target))
}
}
}
return -1
}
func (c coord) heuristic(target coord) int {
return (target.x - c.x) + (target.y - c.y)
}
func (s coord) iterate(impassable map[coord]bool) []coord {
var ret []coord
for _, step := range []coord{{1, 0}, {-1, 0}, {0, 1}, {0, -1}} {
next := s.add(step)
if impassable[next] || next.x < 0 || next.x > maxCoord || next.y < 0 || next.y > maxCoord {
continue
}
ret = append(ret, next)
}
return ret
}