Browse Source

Tidy up and optimise day 10

master
Chris Smith 4 years ago
parent
commit
02c473b199
Signed by: Chris Smith <chris@chameth.com> GPG Key ID: 3A2D4BBDC4A3C9A9
1 changed files with 47 additions and 35 deletions
  1. 47
    35
      10/main.go

+ 47
- 35
10/main.go View File

23
 }
23
 }
24
 
24
 
25
 func checkAngles(asteroid1 *asteroid, others []*asteroid, countVisible bool) map[float64][]*asteroid {
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
 	for _, asteroid2 := range others {
27
 	for _, asteroid2 := range others {
28
 		if asteroid2 == asteroid1 {
28
 		if asteroid2 == asteroid1 {
29
 			continue
29
 			continue
34
 			angle += math.Pi * 2
34
 			angle += math.Pi * 2
35
 		}
35
 		}
36
 
36
 
37
-		if len(angles[angle]) == 0 && countVisible {
37
+		if countVisible && len(angles[angle]) == 0 {
38
 			asteroid1.visible++
38
 			asteroid1.visible++
39
 			asteroid2.visible++
39
 			asteroid2.visible++
40
 		}
40
 		}
44
 	return angles
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
 	for i, asteroid1 := range asteroids {
48
 	for i, asteroid1 := range asteroids {
55
 		checkAngles(asteroid1, asteroids[i+1:], true)
49
 		checkAngles(asteroid1, asteroids[i+1:], true)
56
 		if best == nil || asteroid1.visible > best.visible {
50
 		if best == nil || asteroid1.visible > best.visible {
57
 			best = asteroid1
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
 	angles := make([]float64, 0, len(targets))
71
 	angles := make([]float64, 0, len(targets))
69
 	for k := range targets {
72
 	for k := range targets {
70
 		angles = append(angles, k)
73
 		angles = append(angles, k)
71
 	}
74
 	}
72
 	sort.Float64s(angles)
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
 	var destroyed *asteroid
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
 	if destroyed == nil {
112
 	if destroyed == nil {
102
 		panic("Universe doesn't make sense. Reboot and try again?")
113
 		panic("Universe doesn't make sense. Reboot and try again?")
103
 	}
114
 	}
104
 
115
 
116
+	println(best.visible)
105
 	println(destroyed.x*100 + destroyed.y)
117
 	println(destroyed.x*100 + destroyed.y)
106
 }
118
 }

Loading…
Cancel
Save