-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
128 lines (111 loc) · 2.1 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
package main
import (
"bufio"
"fmt"
"os"
"sort"
)
func main() {
var input []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input = append(input, scanner.Text())
}
stars := parseInput(input)
steps := findConstellation(stars)
fmt.Println("Part 1:")
printConstellation(stars)
fmt.Println()
fmt.Printf("Part 2: %d\n", steps)
}
func parseInput(input []string) []*star {
var stars []*star
for _, line := range input {
var x, y, vx, vy int
if _, err := fmt.Sscanf(
line,
"position=<%d, %d> velocity=<%d, %d>", &x, &y, &vx, &vy,
); err != nil {
break
}
stars = append(stars, &star{x, y, vx, vy})
}
return stars
}
type star struct {
x, y int
vx, vy int
}
// findConstellation moves the stars until it arrives at the correct
// constellation and returns the number of steps needed to get there.
func findConstellation(stars []*star) (steps int) {
area := totalArea(stars)
var lastArea int
for {
move(stars, 1)
lastArea = area
area = totalArea(stars)
if lastArea < area {
break
}
steps++
}
move(stars, -1)
return steps
}
func move(stars []*star, steps int) {
for _, s := range stars {
s.x += s.vx * steps
s.y += s.vy * steps
}
}
func totalArea(stars []*star) int {
if len(stars) == 0 {
return 0
}
x1 := stars[0].x
y1 := stars[0].y
x2, y2 := x1, y1
for _, s := range stars {
if s.x < x1 {
x1 = s.x
}
if s.x > x2 {
x2 = s.x
}
if s.y < y1 {
y1 = s.y
}
if s.y > y2 {
y2 = s.y
}
}
return (x2 - x1) * (y2 - y1)
}
func printConstellation(stars []*star) {
sort.Slice(stars, func(i, j int) bool {
if stars[i].y == stars[j].y {
return stars[i].x < stars[j].x
}
return stars[i].y < stars[j].y
})
x1, y1 := stars[0].x, stars[0].y
x2, y2 := stars[len(stars)-1].x, stars[len(stars)-1].y
starGrid := make([][]bool, y2-y1+1)
for y := range starGrid {
starGrid[y] = make([]bool, x2-x1+1)
}
for _, s := range stars {
starGrid[s.y-y1][s.x-x1] = true
}
for y := range starGrid {
for x := range starGrid[y] {
if starGrid[y][x] {
fmt.Print("#")
} else {
fmt.Print(".")
}
}
fmt.Println()
}
}