-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
121 lines (92 loc) · 1.97 KB
/
main.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
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
var input []string
for s := bufio.NewScanner(os.Stdin); s.Scan(); {
input = append(input, s.Text())
}
fmt.Printf("Part 1: %d\n", part1(input))
fmt.Printf("Part 2: %d\n", part2(input))
}
func part1(input []string) int {
if len(input) == 0 {
return 0
}
guard, grid := parse(input)
seen := make(map[Coord]bool)
walk(guard, grid, func(guard Guard) bool {
seen[guard.loc] = true
return true
})
return len(seen)
}
func part2(input []string) int {
if len(input) == 0 {
return 0
}
guard, grid := parse(input)
candidates := make(map[Coord]bool)
walk(guard, grid, func(guard Guard) bool {
candidates[guard.loc] = true
return true
})
var sum int
for c := range candidates {
grid[c] = 'O'
seen := make(map[Guard]bool)
walk(guard, grid, func(guard Guard) bool {
if seen[guard] {
sum++
return false
}
seen[guard] = true
return true
})
grid[c] = '.'
}
return sum
}
type Guard struct {
dir byte
loc Coord
}
type Coord struct {
x, y int
}
func parse(input []string) (Guard, map[Coord]byte) {
var guard Guard
grid := make(map[Coord]byte)
for y := range input {
for x := range input[y] {
if input[y][x] == '^' {
guard = Guard{dir: input[y][x], loc: Coord{x, y}}
grid[Coord{x, y}] = '.'
} else {
grid[Coord{x, y}] = input[y][x]
}
}
}
return guard, grid
}
// walk moves the guard through the grid until f returns false.
func walk(guard Guard, grid map[Coord]byte, f func(Guard) bool) {
for grid[guard.loc] != 0 && f(guard) {
const dirs = "^>v<"
next := map[byte]Coord{
'^': Coord{guard.loc.x, guard.loc.y - 1},
'>': Coord{guard.loc.x + 1, guard.loc.y},
'v': Coord{guard.loc.x, guard.loc.y + 1},
'<': Coord{guard.loc.x - 1, guard.loc.y},
}
if block := grid[next[guard.dir]]; block != '.' && block != 0 {
guard.dir = dirs[(strings.IndexByte(dirs, guard.dir)+1)%4]
} else {
guard.loc = next[guard.dir]
}
}
}