-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path16.go
105 lines (99 loc) · 2.68 KB
/
16.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
package main
import "bufio"
import "os"
import "fmt"
import "slices"
type pos struct { row, col int }
type dir struct { dr, dc int }
type posdir struct { p pos; d dir }
var maze [][]rune
var start, end pos
func part1() (score int) {
type state struct { p pos; d dir; score int }
var queue []state
var processed = make(map[posdir]bool)
var enqueue = func (p pos, d dir, score int) {
for i := 0; i < len(queue); i++ {
if queue[i].score >= score {
queue = slices.Insert(queue, i, state{p, d, score})
return
}
}
queue = append(queue, state{p, d, score})
}
enqueue(start, dir{0, 1}, 0)
for len(queue) > 0 {
var st = queue[0]
queue = queue[1:]
var pd = posdir{st.p, st.d}
if processed[pd] { continue }
processed[pd] = true
if st.p == end {
score = st.score
return
}
var next = pos{st.p.row + st.d.dr, st.p.col + st.d.dc}
if maze[next.row][next.col] != '#' {
enqueue(next, st.d, st.score + 1)
}
enqueue(st.p, dir{st.d.dc, -st.d.dr}, st.score + 1000)
enqueue(st.p, dir{-st.d.dc, st.d.dr}, st.score + 1000)
}
return
}
func part2() int {
type state struct { p pos; d dir; score int; path map[pos]bool }
var queue []state
var processed = make(map[posdir]int)
var enqueue = func (p pos, d dir, score int, path map[pos]bool) {
var extended = make(map[pos]bool)
for p, _ := range path { extended[p] = true }
extended[p] = true
for i := 0; i < len(queue); i++ {
if queue[i].score >= score {
queue = slices.Insert(queue, i, state{p, d, score, extended})
return
}
}
queue = append(queue, state{p, d, score, extended})
}
var singleton = make(map[pos]bool)
singleton[start] = true
var seats = make(map[pos]bool)
var minscore = 1000000000
enqueue(start, dir{0, 1}, 0, singleton)
for len(queue) > 0 {
var st = queue[0]
queue = queue[1:]
if st.score > minscore { continue }
var pd = posdir{st.p, st.d}
if v, ok := processed[pd]; ok && st.score > v { continue }
processed[pd] = st.score
if st.p == end {
if st.score < minscore { minscore = st.score }
for p, _ := range st.path { seats[p] = true }
}
var next = pos{st.p.row + st.d.dr, st.p.col + st.d.dc}
if maze[next.row][next.col] != '#' {
enqueue(next, st.d, st.score + 1, st.path)
}
enqueue(st.p, dir{st.d.dc, -st.d.dr}, st.score + 1000, st.path)
enqueue(st.p, dir{-st.d.dc, st.d.dr}, st.score + 1000, st.path)
}
return len(seats)
}
func main() {
var scanner = bufio.NewScanner(os.Stdin)
var row = 0
for scanner.Scan() {
var line = scanner.Text()
for col, cell := range line {
if cell == 'S' { start = pos{row, col} }
if cell == 'E' { end = pos{row, col} }
}
maze = append(maze, []rune(line))
row++
}
fmt.Print(part1())
fmt.Println(" ", part2())
}