-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
88 lines (72 loc) · 1.65 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
package main
import (
"fmt"
"math"
"os"
"github.com/devries/advent_of_code_2021/utils"
)
func main() {
f, err := os.Open("../inputs/day17.txt")
utils.Check(err, "error opening input file")
defer f.Close()
lines := utils.ReadLines(f)
var xmin, xmax, ymin, ymax int
_, err = fmt.Sscanf(lines[0], "target area: x=%d..%d, y=%d..%d", &xmin, &xmax, &ymin, &ymax)
utils.Check(err, "unable to parse input")
r := solve(xmin, xmax, ymin, ymax)
fmt.Println(r)
}
func solve(xmin, xmax, ymin, ymax int) int {
found := make(map[utils.Point]bool)
for vy := maxVy(ymin); vy > -maxVy(ymin); vy-- {
stepsA := stepsFromY(ymax, vy)
stepsB := stepsFromY(ymin, vy)
for s := stepsA - 1; s <= stepsB+1; s++ {
if s < 1 {
continue
}
y := ypos(vy, s)
vxmin := minVx(xmin)
for vx := vxmin; true; vx++ {
x := xpos(vx, s)
if x <= xmax && x >= xmin && y <= ymax && y >= ymin {
// fmt.Printf("pos: (%d,%d), vx=%d, vy=%d\n", x, ypos(vy, s), vxmin, vy)
found[utils.Point{X: vx, Y: vy}] = true
}
if x > xmax {
break
}
}
}
}
return len(found)
}
func maxVy(y int) int {
if y > 0 {
return y
}
return -y + 1
}
func minVx(x int) int {
sq := math.Sqrt(1.0 + 8.0*float64(x))
return int((sq + 1.0) / 2.0)
}
func ypos(vy, steps int) int {
return steps*vy - steps*(steps-1)/2
}
func xpos(vx, steps int) int {
if steps > vx {
return vx * (vx + 1) / 2
}
return (2*vx - steps + 1) * steps / 2
}
func stepsFromY(y, vy int) int {
b := float64(2*vy + 1)
srt := math.Sqrt(b*b - 8.0*float64(y))
sola := (b + srt) / 2.0
solb := (b - srt) / 2.0
if solb > 0.0 {
fmt.Println("Need to consider another domain")
}
return int(sola)
}