diff --git a/DIRECTORY.md b/DIRECTORY.md index ac27b183e8f..0b52add4891 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -86,6 +86,7 @@ * [RGB-CMYK Conversion](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/rgb_cmyk_conversion.rs) * [RGB-HSV Conversion](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/rgb_hsv_conversion.rs) * [Roman Numerals](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/roman_numerals.rs) + * [Speed](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/speed.rs) * [Time Units](https://github.com/TheAlgorithms/Rust/blob/master/src/conversions/time_units.rs) * Data Structures * [AVL Tree](https://github.com/TheAlgorithms/Rust/blob/master/src/data_structures/avl_tree.rs) diff --git a/src/conversions/mod.rs b/src/conversions/mod.rs index 6f7b9955f23..1c38f04754e 100644 --- a/src/conversions/mod.rs +++ b/src/conversions/mod.rs @@ -16,6 +16,7 @@ mod order_of_magnitude_conversion; mod rgb_cmyk_conversion; mod rgb_hsv_conversion; mod roman_numerals; +mod speed; mod time_units; pub use self::binary_to_decimal::binary_to_decimal; @@ -38,4 +39,5 @@ pub use self::order_of_magnitude_conversion::{ pub use self::rgb_cmyk_conversion::rgb_to_cmyk; pub use self::rgb_hsv_conversion::{hsv_to_rgb, rgb_to_hsv, ColorError, Hsv, Rgb}; pub use self::roman_numerals::{int_to_roman, roman_to_int}; +pub use self::speed::{convert_speed, SpeedUnit}; pub use self::time_units::convert_time; diff --git a/src/conversions/speed.rs b/src/conversions/speed.rs new file mode 100644 index 00000000000..28e34605959 --- /dev/null +++ b/src/conversions/speed.rs @@ -0,0 +1,230 @@ +//! Convert speed units +//! +//! References: +//! - +//! - +//! - +//! - +//! - +//! - +//! - + +use std::fmt; + +/// Supported speed units +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum SpeedUnit { + /// Kilometers per hour (km/h) + KilometersPerHour, + /// Meters per second (m/s) - SI derived unit + MetersPerSecond, + /// Miles per hour (mph) + MilesPerHour, + /// Nautical miles per hour (knot) + Knot, + /// Feet per second (fps or ft/s) + FeetPerSecond, + /// Mach number (dimensionless) - speed divided by speed of sound at sea level (340.3 m/s) + Mach, + /// Speed of light (c) - speed divided by speed of light in vacuum (299,792,458 m/s) + SpeedOfLight, +} + +impl fmt::Display for SpeedUnit { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + SpeedUnit::KilometersPerHour => write!(f, "km/h"), + SpeedUnit::MetersPerSecond => write!(f, "m/s"), + SpeedUnit::MilesPerHour => write!(f, "mph"), + SpeedUnit::Knot => write!(f, "knot"), + SpeedUnit::FeetPerSecond => write!(f, "ft/s"), + SpeedUnit::Mach => write!(f, "Mach"), + SpeedUnit::SpeedOfLight => write!(f, "c"), + } + } +} + +impl SpeedUnit { + /// Get the conversion factor to km/h + fn as_kmh_multiplier(self) -> f64 { + match self { + SpeedUnit::KilometersPerHour => 1.0, + SpeedUnit::MetersPerSecond => 3.6, + SpeedUnit::MilesPerHour => 1.609344, + SpeedUnit::Knot => 1.852, + SpeedUnit::FeetPerSecond => 1.09728, + SpeedUnit::Mach => 1225.08, + SpeedUnit::SpeedOfLight => 1_079_252_848.8, + } + } + + /// Get the conversion factor from km/h to this unit + fn kmh_multiplier(self) -> f64 { + match self { + SpeedUnit::KilometersPerHour => 1.0, + SpeedUnit::MetersPerSecond => 0.277777778, + SpeedUnit::MilesPerHour => 0.621371192, + SpeedUnit::Knot => 0.539956803, + SpeedUnit::FeetPerSecond => 0.911344415, + SpeedUnit::Mach => 0.000816164, + SpeedUnit::SpeedOfLight => 9.265669311e-10, + } + } +} + +/// Convert speed from one unit to another +/// +/// # Arguments +/// +/// * `speed` - The speed value to convert +/// * `from` - The unit to convert from +/// * `to` - The unit to convert to +/// +/// # Returns +/// +/// The converted speed value rounded to 3 decimal places +pub fn convert_speed(speed: f64, from: SpeedUnit, to: SpeedUnit) -> f64 { + let kmh = speed * from.as_kmh_multiplier(); + let result = kmh * to.kmh_multiplier(); + (result * 1000.0).round() / 1000.0 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_speed_conversion() { + assert_eq!( + convert_speed( + 100.0, + SpeedUnit::KilometersPerHour, + SpeedUnit::MetersPerSecond + ), + 27.778 + ); + assert_eq!( + convert_speed(100.0, SpeedUnit::KilometersPerHour, SpeedUnit::MilesPerHour), + 62.137 + ); + assert_eq!( + convert_speed(100.0, SpeedUnit::KilometersPerHour, SpeedUnit::Knot), + 53.996 + ); + assert_eq!( + convert_speed( + 100.0, + SpeedUnit::MetersPerSecond, + SpeedUnit::KilometersPerHour + ), + 360.0 + ); + assert_eq!( + convert_speed(100.0, SpeedUnit::MetersPerSecond, SpeedUnit::MilesPerHour), + 223.694 + ); + assert_eq!( + convert_speed(100.0, SpeedUnit::MetersPerSecond, SpeedUnit::Knot), + 194.384 + ); + assert_eq!( + convert_speed(100.0, SpeedUnit::MilesPerHour, SpeedUnit::KilometersPerHour), + 160.934 + ); + assert_eq!( + convert_speed(100.0, SpeedUnit::MilesPerHour, SpeedUnit::MetersPerSecond), + 44.704 + ); + assert_eq!( + convert_speed(100.0, SpeedUnit::MilesPerHour, SpeedUnit::Knot), + 86.898 + ); + assert_eq!( + convert_speed(100.0, SpeedUnit::Knot, SpeedUnit::KilometersPerHour), + 185.2 + ); + assert_eq!( + convert_speed(100.0, SpeedUnit::Knot, SpeedUnit::MetersPerSecond), + 51.444 + ); + assert_eq!( + convert_speed(100.0, SpeedUnit::Knot, SpeedUnit::MilesPerHour), + 115.078 + ); + assert_eq!( + convert_speed(100.0, SpeedUnit::FeetPerSecond, SpeedUnit::MetersPerSecond), + 30.48 + ); + assert_eq!( + convert_speed(100.0, SpeedUnit::MetersPerSecond, SpeedUnit::FeetPerSecond), + 328.084 + ); + assert_eq!( + convert_speed( + 100.0, + SpeedUnit::FeetPerSecond, + SpeedUnit::KilometersPerHour + ), + 109.728 + ); + assert_eq!( + convert_speed(100.0, SpeedUnit::FeetPerSecond, SpeedUnit::MilesPerHour), + 68.182 + ); + assert_eq!( + convert_speed(1.0, SpeedUnit::Mach, SpeedUnit::KilometersPerHour), + 1225.08 + ); + assert_eq!( + convert_speed(1.0, SpeedUnit::Mach, SpeedUnit::MetersPerSecond), + 340.3 + ); + assert_eq!( + convert_speed(1000.0, SpeedUnit::KilometersPerHour, SpeedUnit::Mach), + 0.816 + ); + assert_eq!( + convert_speed(2.0, SpeedUnit::Mach, SpeedUnit::KilometersPerHour), + 2450.16 + ); + assert_eq!( + convert_speed(1.0, SpeedUnit::SpeedOfLight, SpeedUnit::MetersPerSecond), + 299792458.24 + ); + assert_eq!( + convert_speed(1.0, SpeedUnit::SpeedOfLight, SpeedUnit::KilometersPerHour), + 1079252848.8 + ); + assert_eq!( + convert_speed( + 299792458.0, + SpeedUnit::MetersPerSecond, + SpeedUnit::SpeedOfLight + ), + 1.0 + ); + assert_eq!( + convert_speed(0.1, SpeedUnit::SpeedOfLight, SpeedUnit::MetersPerSecond), + 29979245.824 + ); + assert_eq!( + convert_speed( + 100.0, + SpeedUnit::KilometersPerHour, + SpeedUnit::KilometersPerHour + ), + 100.0 + ); + } + + #[test] + fn test_display() { + assert_eq!(SpeedUnit::KilometersPerHour.to_string(), "km/h"); + assert_eq!(SpeedUnit::MetersPerSecond.to_string(), "m/s"); + assert_eq!(SpeedUnit::MilesPerHour.to_string(), "mph"); + assert_eq!(SpeedUnit::Knot.to_string(), "knot"); + assert_eq!(SpeedUnit::FeetPerSecond.to_string(), "ft/s"); + assert_eq!(SpeedUnit::Mach.to_string(), "Mach"); + assert_eq!(SpeedUnit::SpeedOfLight.to_string(), "c"); + } +}