diff --git a/maths/free_fall_distance.rb b/maths/free_fall_distance.rb new file mode 100644 index 0000000..2aee86a --- /dev/null +++ b/maths/free_fall_distance.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# Free-fall helpers based on constant acceleration motion. +class FreeFallDistance + STANDARD_GRAVITY = 9.80665 + + class << self + # d = 0.5 * g * t^2 + def distance(time:, gravity: STANDARD_GRAVITY) + raise ArgumentError, 'time must be non-negative' if time.negative? + raise ArgumentError, 'gravity must be positive' unless gravity.positive? + + 0.5 * gravity * time * time + end + + # t = sqrt(2d / g) + def time(distance:, gravity: STANDARD_GRAVITY) + raise ArgumentError, 'distance must be non-negative' if distance.negative? + raise ArgumentError, 'gravity must be positive' unless gravity.positive? + + Math.sqrt((2.0 * distance) / gravity) + end + end +end diff --git a/maths/free_fall_distance_test.rb b/maths/free_fall_distance_test.rb new file mode 100644 index 0000000..ae25015 --- /dev/null +++ b/maths/free_fall_distance_test.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'minitest/autorun' +require_relative './free_fall_distance' + +class FreeFallDistanceTest < Minitest::Test + def test_distance_from_time + assert_in_delta 19.6133, FreeFallDistance.distance(time: 2.0), 1E-4 + end + + def test_time_from_distance + assert_in_delta 2.0, FreeFallDistance.time(distance: 19.6133), 1E-4 + end + + def test_negative_time_raises + assert_raises DomainError do + FreeFallDistance.distance(time: -1.0) + end + end + + def test_negative_distance_raises + assert_raises DomainError do + FreeFallDistance.time(distance: -1.0) + end + end +end