From e78a1fce4f5102d1e4f76e7f5309cedde966be26 Mon Sep 17 00:00:00 2001 From: nickzerjeski Date: Mon, 13 Apr 2026 10:51:29 +0200 Subject: [PATCH] feat: add time free kinematic equation solver Fixes: #193 --- maths/time_free_equation.rb | 35 +++++++++++++++++++++++++++++++ maths/time_free_equation_test.rb | 36 ++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 maths/time_free_equation.rb create mode 100644 maths/time_free_equation_test.rb diff --git a/maths/time_free_equation.rb b/maths/time_free_equation.rb new file mode 100644 index 0000000..584f600 --- /dev/null +++ b/maths/time_free_equation.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +# Solves forms of the kinematic equation: +# vf^2 - vi^2 = 2 * a * delta_x +class TimeFreeEquation + class << self + def displacement(initial_velocity:, final_velocity:, acceleration:) + raise ZeroDivisionError, 'acceleration cannot be zero' if acceleration.zero? + + ((final_velocity**2) - (initial_velocity**2)) / (2.0 * acceleration) + end + + def acceleration(initial_velocity:, final_velocity:, displacement:) + raise ZeroDivisionError, 'displacement cannot be zero' if displacement.zero? + + ((final_velocity**2) - (initial_velocity**2)) / (2.0 * displacement) + end + + def final_velocity(initial_velocity:, acceleration:, displacement:) + value = (initial_velocity**2) + (2.0 * acceleration * displacement) + raise DomainError, 'final velocity is not real for the provided inputs' if value.negative? + + Math.sqrt(value) + end + + def initial_velocity(final_velocity:, acceleration:, displacement:) + value = (final_velocity**2) - (2.0 * acceleration * displacement) + raise DomainError, 'initial velocity is not real for the provided inputs' if value.negative? + + Math.sqrt(value) + end + end +end + +class DomainError < StandardError; end diff --git a/maths/time_free_equation_test.rb b/maths/time_free_equation_test.rb new file mode 100644 index 0000000..777760e --- /dev/null +++ b/maths/time_free_equation_test.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'minitest/autorun' +require_relative './time_free_equation' + +class TimeFreeEquationTest < Minitest::Test + def test_displacement + assert_in_delta 24.0, + TimeFreeEquation.displacement(initial_velocity: 2.0, final_velocity: 10.0, acceleration: 2.0), + 1E-12 + end + + def test_acceleration + assert_in_delta 3.0, + TimeFreeEquation.acceleration(initial_velocity: 4.0, final_velocity: 10.0, displacement: 14.0), + 1E-12 + end + + def test_final_velocity + assert_in_delta 13.0, + TimeFreeEquation.final_velocity(initial_velocity: 5.0, acceleration: 3.0, displacement: 24.0), + 1E-12 + end + + def test_initial_velocity + assert_in_delta 6.0, + TimeFreeEquation.initial_velocity(final_velocity: 14.0, acceleration: 4.0, displacement: 20.0), + 1E-12 + end + + def test_domain_error_for_imaginary_velocity + assert_raises DomainError do + TimeFreeEquation.final_velocity(initial_velocity: 1.0, acceleration: -10.0, displacement: 1.0) + end + end +end