From 1d3d18bcd28cd4eb0ffb7b1db213215f2f92c78a Mon Sep 17 00:00:00 2001 From: Aviv Faraj <73610201+avivfaraj@users.noreply.github.com> Date: Mon, 4 Apr 2022 16:44:29 +0300 Subject: [PATCH] horizontal motion code physics (#4710) * Add files via upload * Changed print to f-string Also printed out results in a math notation * Add files via upload * Fixes: #4710 provided return type * File exists in another pull request * imported radians from math * Updated file according to pre-commit test * Updated file * Updated gamma * Deleted duplicate file * removed pi * reversed tests * Fixed angle condition * Modified prints to f-string * Update horizontal_projectile_motion.py * Update horizontal_projectile_motion.py * Fixes #4710 added exceptions and tests * Added float tests * Fixed type annotations * Fixed last annotation * Fixed annotations * fixed format * Revert "fixed format" This reverts commit 5b0249ac0a0f9c36c3cfbab8423eb72925a73ffb. Undo changes @wq * Revert "Fixed annotations" This reverts commit c37bb9540834cb77e37822eb376a5896cda34778. * Revert "Fixed last annotation" This reverts commit e3678fdeadd23f1bfca27015ab524efa184f6c79. * Revert "Fixed type annotations" This reverts commit 3f2b238c34cd926b335d1f6f750e009f08e8f270. * Revert to 4e2fcaf6fb * Fixing errors found during pre-commit --- physics/horizontal_projectile_motion.py | 152 ++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 physics/horizontal_projectile_motion.py diff --git a/physics/horizontal_projectile_motion.py b/physics/horizontal_projectile_motion.py new file mode 100644 index 000000000..0f27b0617 --- /dev/null +++ b/physics/horizontal_projectile_motion.py @@ -0,0 +1,152 @@ +""" +Horizontal Projectile Motion problem in physics. +This algorithm solves a specific problem in which +the motion starts from the ground as can be seen below: + (v = 0) + ** + * * + * * + * * + * * + * * +GROUND GROUND +For more info: https://en.wikipedia.org/wiki/Projectile_motion +""" + +# Importing packages +from math import radians as angle_to_radians +from math import sin + +# Acceleration Constant on hearth (unit m/s^2) +g = 9.80665 + + +def check_args(init_velocity: float, angle: float) -> None: + """ + Check that the arguments are valid + """ + + # Ensure valid instance + if not isinstance(init_velocity, (int, float)): + raise TypeError("Invalid velocity. Should be a positive number.") + + if not isinstance(angle, (int, float)): + raise TypeError("Invalid angle. Range is 1-90 degrees.") + + # Ensure valid angle + if angle > 90 or angle < 1: + raise ValueError("Invalid angle. Range is 1-90 degrees.") + + # Ensure valid velocity + if init_velocity < 0: + raise ValueError("Invalid velocity. Should be a positive number.") + + +def horizontal_distance(init_velocity: float, angle: float) -> float: + """ + Returns the horizontal distance that the object cover + Formula: + v_0^2 * sin(2 * alpha) + --------------------- + g + v_0 - initial velocity + alpha - angle + >>> horizontal_distance(30, 45) + 91.77 + >>> horizontal_distance(100, 78) + 414.76 + >>> horizontal_distance(-1, 20) + Traceback (most recent call last): + ... + ValueError: Invalid velocity. Should be a positive number. + >>> horizontal_distance(30, -20) + Traceback (most recent call last): + ... + ValueError: Invalid angle. Range is 1-90 degrees. + """ + check_args(init_velocity, angle) + radians = angle_to_radians(2 * angle) + return round(init_velocity**2 * sin(radians) / g, 2) + + +def max_height(init_velocity: float, angle: float) -> float: + """ + Returns the maximum height that the object reach + Formula: + v_0^2 * sin^2(alpha) + -------------------- + 2g + v_0 - initial velocity + alpha - angle + >>> max_height(30, 45) + 22.94 + >>> max_height(100, 78) + 487.82 + >>> max_height("a", 20) + Traceback (most recent call last): + ... + TypeError: Invalid velocity. Should be a positive number. + >>> horizontal_distance(30, "b") + Traceback (most recent call last): + ... + TypeError: Invalid angle. Range is 1-90 degrees. + """ + check_args(init_velocity, angle) + radians = angle_to_radians(angle) + return round(init_velocity**2 * sin(radians) ** 2 / (2 * g), 2) + + +def total_time(init_velocity: float, angle: float) -> float: + """ + Returns total time of the motion + Formula: + 2 * v_0 * sin(alpha) + -------------------- + g + v_0 - initial velocity + alpha - angle + >>> total_time(30, 45) + 4.33 + >>> total_time(100, 78) + 19.95 + >>> total_time(-10, 40) + Traceback (most recent call last): + ... + ValueError: Invalid velocity. Should be a positive number. + >>> total_time(30, "b") + Traceback (most recent call last): + ... + TypeError: Invalid angle. Range is 1-90 degrees. + """ + check_args(init_velocity, angle) + radians = angle_to_radians(angle) + return round(2 * init_velocity * sin(radians) / g, 2) + + +def test_motion() -> None: + """ + >>> test_motion() + """ + v0, angle = 25, 20 + assert horizontal_distance(v0, angle) == 40.97 + assert max_height(v0, angle) == 3.73 + assert total_time(v0, angle) == 1.74 + + +if __name__ == "__main__": + from doctest import testmod + + testmod() + + # Get input from user + init_vel = float(input("Initial Velocity: ").strip()) + + # Get input from user + angle = float(input("angle: ").strip()) + + # Print results + print() + print("Results: ") + print(f"Horizontal Distance: {str(horizontal_distance(init_vel, angle))} [m]") + print(f"Maximum Height: {str(max_height(init_vel, angle))} [m]") + print(f"Total Time: {str(total_time(init_vel, angle))} [s]")