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,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
 }

Loading…
Cancel
Save