-
Notifications
You must be signed in to change notification settings - Fork 1
/
prob317.py
114 lines (85 loc) · 2.8 KB
/
prob317.py
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
"""
Solve Project Euler Problem 317
Find the volume of of the region travelled by a firecracker fragments
"""
import sys
import matplotlib.pylab as plt
import numpy as np
X_0 = 0.0 # meters
Y_0 = 100.0 # meters
V_0 = 20.0 # meters/second
G = -9.81 # meters/second^2
TIME_SAMPLE_COUNT = 20000
ANGLE_SAMPLE_COUNT = 2000
MIN_ANGLE = 0.0
MAX_ANGLE = np.pi/2
X_POINTS = 20000
def solve_quad(a, b, c):
"""Solve quadratic equation ax^2 + bx + c = 0"""
discriminant = b**2 - 4*a*c
return ((-b+np.sqrt(discriminant))/(2.0*a),
(-b-np.sqrt(discriminant))/(2.0*a))
def trace_path(angle, times=None):
"""
Given the angle of departure, compute the path through 2-D space
of a firework fragment.
"""
if times is None:
t_max = airtime(angle)
print "t_max is", t_max
times = np.linspace(0, t_max, TIME_SAMPLE_COUNT)
# Find the longest time aloft
v0_x = V_0 * np.cos(angle)
v0_y = V_0 * np.sin(angle)
x = v0_x*times + X_0
y = G*times**2 + v0_y*times + Y_0
return x, y
def airtime(angle):
"""Given the angle of departure, compute the time the particle is aloft."""
v0_x = V_0 * np.sin(angle)
v0_y = V_0 * np.cos(angle)
times = solve_quad(G, v0_y, Y_0)
t_max = np.max(times)
return t_max
def generate_path_set():
angles = np.linspace(MIN_ANGLE, MAX_ANGLE, ANGLE_SAMPLE_COUNT)
times = np.array([airtime(angle) for angle in angles])
t = np.linspace(0, max(times), TIME_SAMPLE_COUNT)
x = np.zeros((ANGLE_SAMPLE_COUNT, TIME_SAMPLE_COUNT))
y = np.zeros((ANGLE_SAMPLE_COUNT, TIME_SAMPLE_COUNT))
for (i, angle) in enumerate(angles):
x[i,:], y[i,:] = trace_path(angle, t)
return x, y
def interpolate_curves(x_raw, y_raw):
x_interp = np.linspace(0, np.max(x_raw), X_POINTS)
y_interp = []
for x, y in zip(x_raw, y_raw):
y_interp.append(np.interp(x_interp, x, y))
return x_interp, np.array(y_interp)
def generate_bounding_curve(x_interp, y_interp):
y_bound = y_interp.max(axis=0)
criteria = y_bound >= 1E-10
y_bound = y_bound[criteria]
x_bound = x_interp[criteria]
return x_bound, y_bound
def do_solid_integration(x_bound, y_bound):
f = x_bound * y_bound
return 2*np.pi * np.trapz(f, x_bound)
def solve():
x_raw, y_raw = generate_path_set()
x_interp, y_interp = interpolate_curves(x_raw, y_raw)
x_bound, y_bound = generate_bounding_curve(x_interp, y_interp)
plt.plot(x_bound, y_bound, 'k-')
print do_solid_integration(x_bound, y_bound)
plt.show()
def main(argv=None):
if argv is None:
argv = sys.argv[1:]
solve()
return
x, y = trace_path(np.pi/4)
import matplotlib.pylab as plt
plt.plot(x, y)
plt.show()
if __name__ == "__main__":
main()