-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
140 lines (122 loc) · 3.09 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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"fmt"
"github.com/Alex-Waring/AoC/utils"
)
func part1(input []string) map[utils.Position]bool {
defer utils.Timer("part1")()
board := utils.NewBoard()
location := utils.Location{}
for r, row := range input {
for c, char := range row {
if char == '^' {
location = utils.Location{
Pos: utils.NewPosition(r, c),
Dir: utils.Up,
}
board[utils.Position{Row: r, Col: c}] = "."
} else {
board[utils.Position{Row: r, Col: c}] = string(char)
}
}
}
places_been := map[utils.Position]bool{}
places_been[location.Pos] = true
for true {
// Move the location in the direction it's facing
new_pos := location.Pos.Move(location.Dir, 1)
// If the new position is off the board, stop
if _, ok := board[new_pos]; !ok {
break
}
// If the new position is a wall, turn right
if board[new_pos] == "#" {
location.Dir = location.Dir.Turn(utils.Right)
new_pos = location.Pos.Move(location.Dir, 1)
}
// If the new position is open space, move there
location.Pos = new_pos
places_been[location.Pos] = true
}
fmt.Println(len(places_been))
return places_been
}
func part2(input []string) {
defer utils.Timer("part2")()
board := utils.NewBoard()
start_location := utils.Location{}
for r, row := range input {
for c, char := range row {
if char == '^' {
start_location = utils.Location{
Pos: utils.NewPosition(r, c),
Dir: utils.Up,
}
board[utils.Position{Row: r, Col: c}] = "."
} else {
board[utils.Position{Row: r, Col: c}] = string(char)
}
}
}
// Do part 1 to find the places we've been
places_to_check := part1(input)
// Add a new obstruction to the board
found_loops := 0
tried := 0
for obstruction := range places_to_check {
tried++
if tried%1000 == 0 {
fmt.Println(tried)
}
if board[obstruction] == "#" || board[obstruction] == "^" {
continue
}
old_char := board[obstruction]
board[obstruction] = "#"
location := utils.Location{
Pos: utils.Position{
Row: start_location.Pos.Row,
Col: start_location.Pos.Col,
},
Dir: start_location.Dir,
}
places_been := map[utils.Position]bool{}
places_been[location.Pos] = true
loop_tracker := map[utils.Location]bool{}
for true {
// Move the location in the direction it's facing
new_pos := location.Pos.Move(location.Dir, 1)
// If the new position is off the board, stop
if _, ok := board[new_pos]; !ok {
break
}
// If the new position is a wall, turn right, loop until open
for true {
if board[new_pos] == "#" {
location.Dir = location.Dir.Turn(utils.Right)
new_pos = location.Pos.Move(location.Dir, 1)
}
// If the new position is open space, move there
if board[new_pos] == "." {
location.Pos = new_pos
break
}
}
// If we've been here before, we've looped
if _, ok := loop_tracker[location]; ok {
found_loops++
break
} else {
loop_tracker[location] = true
}
places_been[location.Pos] = true
}
board[obstruction] = old_char
}
fmt.Println(found_loops)
}
func main() {
input := utils.ReadInput("input.txt")
part1(input)
part2(input)
}