|
@@ -23,7 +23,7 @@ func buildMap(input []string) []*asteroid {
|
23
|
23
|
}
|
24
|
24
|
|
25
|
25
|
func checkAngles(asteroid1 *asteroid, others []*asteroid, countVisible bool) map[float64][]*asteroid {
|
26
|
|
- angles := make(map[float64][]*asteroid)
|
|
26
|
+ angles := make(map[float64][]*asteroid, len(others))
|
27
|
27
|
for _, asteroid2 := range others {
|
28
|
28
|
if asteroid2 == asteroid1 {
|
29
|
29
|
continue
|
|
@@ -34,7 +34,7 @@ func checkAngles(asteroid1 *asteroid, others []*asteroid, countVisible bool) map
|
34
|
34
|
angle += math.Pi * 2
|
35
|
35
|
}
|
36
|
36
|
|
37
|
|
- if len(angles[angle]) == 0 && countVisible {
|
|
37
|
+ if countVisible && len(angles[angle]) == 0 {
|
38
|
38
|
asteroid1.visible++
|
39
|
39
|
asteroid2.visible++
|
40
|
40
|
}
|
|
@@ -44,63 +44,75 @@ func checkAngles(asteroid1 *asteroid, others []*asteroid, countVisible bool) map
|
44
|
44
|
return angles
|
45
|
45
|
}
|
46
|
46
|
|
47
|
|
-func main() {
|
48
|
|
- var (
|
49
|
|
- input = common.ReadFileAsStrings("10/input.txt")
|
50
|
|
- asteroids = buildMap(input)
|
51
|
|
- best *asteroid
|
52
|
|
- )
|
53
|
|
-
|
|
47
|
+func selectBest(asteroids []*asteroid) (best *asteroid) {
|
54
|
48
|
for i, asteroid1 := range asteroids {
|
55
|
49
|
checkAngles(asteroid1, asteroids[i+1:], true)
|
56
|
50
|
if best == nil || asteroid1.visible > best.visible {
|
57
|
51
|
best = asteroid1
|
58
|
52
|
}
|
59
|
53
|
}
|
|
54
|
+ return
|
|
55
|
+}
|
60
|
56
|
|
61
|
|
- if best == nil {
|
62
|
|
- panic("No asteroids found?")
|
|
57
|
+func closest(origin *asteroid, asteroids []*asteroid) (int, *asteroid) {
|
|
58
|
+ var bestDistance = math.MaxFloat64
|
|
59
|
+ var bestIndex = 0
|
|
60
|
+ for j, target := range asteroids {
|
|
61
|
+ distance := math.Abs(float64(target.x-origin.x)) + math.Abs(float64(target.y-origin.y))
|
|
62
|
+ if distance < bestDistance {
|
|
63
|
+ bestDistance = distance
|
|
64
|
+ bestIndex = j
|
|
65
|
+ }
|
63
|
66
|
}
|
|
67
|
+ return bestIndex, asteroids[bestIndex]
|
|
68
|
+}
|
64
|
69
|
|
65
|
|
- println(best.visible)
|
66
|
|
-
|
67
|
|
- targets := checkAngles(best, asteroids, false)
|
|
70
|
+func sortedAngles(targets map[float64][]*asteroid) []float64 {
|
68
|
71
|
angles := make([]float64, 0, len(targets))
|
69
|
72
|
for k := range targets {
|
70
|
73
|
angles = append(angles, k)
|
71
|
74
|
}
|
72
|
75
|
sort.Float64s(angles)
|
|
76
|
+ return angles
|
|
77
|
+}
|
|
78
|
+
|
|
79
|
+func main() {
|
|
80
|
+ var (
|
|
81
|
+ input = common.ReadFileAsStrings("10/input.txt")
|
|
82
|
+ asteroids = buildMap(input)
|
|
83
|
+ best = selectBest(asteroids)
|
|
84
|
+ targets = checkAngles(best, asteroids, false)
|
|
85
|
+ angles = sortedAngles(targets)
|
|
86
|
+ )
|
73
|
87
|
|
74
|
88
|
var destroyed *asteroid
|
75
|
|
- var i = 0
|
76
|
|
- for n := 0; n < 200; n++ {
|
77
|
|
- if len(targets[angles[i]]) == 1 {
|
78
|
|
- // There's a single target at this angle, skip the angle in the future
|
79
|
|
- destroyed = targets[angles[i]][0]
|
80
|
|
- angles = append(angles[:i], angles[i+1:]...)
|
81
|
|
- } else {
|
82
|
|
- // Multiple targets exists at this angle, remove the closest and move on to the next angle
|
83
|
|
- var bestDistance = math.MaxFloat64
|
84
|
|
- var bestTarget = 0
|
85
|
|
- for j, target := range targets[angles[i]] {
|
86
|
|
- distance := math.Abs(float64(target.x-best.x)) + math.Abs(float64(target.y-best.y))
|
87
|
|
- if distance < bestDistance {
|
88
|
|
- bestDistance = distance
|
89
|
|
- bestTarget = j
|
90
|
|
- }
|
|
89
|
+ if len(angles) >= 200 {
|
|
90
|
+ // We don't complete a full loop, so the answer is just the nearest asteroid at the 200th angle
|
|
91
|
+ _, destroyed = closest(best, targets[angles[199]])
|
|
92
|
+ } else {
|
|
93
|
+ // We loop once, actually simulate the whole thing.
|
|
94
|
+ var i = 0
|
|
95
|
+ for n := 0; n < 200; n++ {
|
|
96
|
+ if len(targets[angles[i]]) == 1 {
|
|
97
|
+ // There's a single target at this angle, skip the angle in the future
|
|
98
|
+ destroyed = targets[angles[i]][0]
|
|
99
|
+ angles = append(angles[:i], angles[i+1:]...)
|
|
100
|
+ } else {
|
|
101
|
+ // Multiple targets exists at this angle, remove the closest and move on to the next angle
|
|
102
|
+ var nearestIndex int
|
|
103
|
+ nearestIndex, destroyed = closest(best, targets[angles[i]])
|
|
104
|
+ targets[angles[i]] = append(targets[angles[i]][:nearestIndex], targets[angles[i]][nearestIndex+1:]...)
|
|
105
|
+ i++
|
91
|
106
|
}
|
92
|
107
|
|
93
|
|
- destroyed = targets[angles[i]][bestTarget]
|
94
|
|
- targets[angles[i]] = append(targets[angles[i]][:bestTarget], targets[angles[i]][bestTarget+1:]...)
|
95
|
|
- i++
|
|
108
|
+ i = i % len(angles)
|
96
|
109
|
}
|
97
|
|
-
|
98
|
|
- i = i % len(angles)
|
99
|
110
|
}
|
100
|
111
|
|
101
|
112
|
if destroyed == nil {
|
102
|
113
|
panic("Universe doesn't make sense. Reboot and try again?")
|
103
|
114
|
}
|
104
|
115
|
|
|
116
|
+ println(best.visible)
|
105
|
117
|
println(destroyed.x*100 + destroyed.y)
|
106
|
118
|
}
|