|
| 1 | +//! Previous Power of Two |
| 2 | +//! |
| 3 | +//! This module provides a function to find the largest power of two that is less than |
| 4 | +//! or equal to a given non-negative integer. |
| 5 | +//! |
| 6 | +//! # Algorithm |
| 7 | +//! |
| 8 | +//! The algorithm works by repeatedly left-shifting (doubling) a power value starting |
| 9 | +//! from 1 until it exceeds the input number, then returning the previous power (by |
| 10 | +//! right-shifting once). |
| 11 | +//! |
| 12 | +//! For more information: <https://stackoverflow.com/questions/1322510> |
| 13 | +
|
| 14 | +/// Finds the largest power of two that is less than or equal to a given integer. |
| 15 | +/// |
| 16 | +/// The function uses bit shifting to efficiently find the power of two. It starts |
| 17 | +/// with 1 and keeps doubling (left shift) until it exceeds the input, then returns |
| 18 | +/// the previous value (right shift). |
| 19 | +/// |
| 20 | +/// # Arguments |
| 21 | +/// |
| 22 | +/// * `number` - A non-negative integer |
| 23 | +/// |
| 24 | +/// # Returns |
| 25 | +/// |
| 26 | +/// A `Result` containing: |
| 27 | +/// - `Ok(u32)` - The largest power of two ≤ the input number |
| 28 | +/// - `Err(String)` - An error message if the input is negative |
| 29 | +/// |
| 30 | +/// # Examples |
| 31 | +/// |
| 32 | +/// ``` |
| 33 | +/// use the_algorithms_rust::bit_manipulation::find_previous_power_of_two; |
| 34 | +/// |
| 35 | +/// assert_eq!(find_previous_power_of_two(0).unwrap(), 0); |
| 36 | +/// assert_eq!(find_previous_power_of_two(1).unwrap(), 1); |
| 37 | +/// assert_eq!(find_previous_power_of_two(2).unwrap(), 2); |
| 38 | +/// assert_eq!(find_previous_power_of_two(3).unwrap(), 2); |
| 39 | +/// assert_eq!(find_previous_power_of_two(4).unwrap(), 4); |
| 40 | +/// assert_eq!(find_previous_power_of_two(5).unwrap(), 4); |
| 41 | +/// assert_eq!(find_previous_power_of_two(8).unwrap(), 8); |
| 42 | +/// assert_eq!(find_previous_power_of_two(15).unwrap(), 8); |
| 43 | +/// assert_eq!(find_previous_power_of_two(16).unwrap(), 16); |
| 44 | +/// assert_eq!(find_previous_power_of_two(17).unwrap(), 16); |
| 45 | +/// |
| 46 | +/// // Negative numbers return an error |
| 47 | +/// assert!(find_previous_power_of_two(-5).is_err()); |
| 48 | +/// ``` |
| 49 | +/// |
| 50 | +/// # Errors |
| 51 | +/// |
| 52 | +/// Returns an error if the input number is negative. |
| 53 | +pub fn find_previous_power_of_two(number: i32) -> Result<u32, String> { |
| 54 | + if number < 0 { |
| 55 | + return Err("Input must be a non-negative integer".to_string()); |
| 56 | + } |
| 57 | + |
| 58 | + let number = number as u32; |
| 59 | + |
| 60 | + if number == 0 { |
| 61 | + return Ok(0); |
| 62 | + } |
| 63 | + |
| 64 | + let mut power = 1u32; |
| 65 | + while power <= number { |
| 66 | + power <<= 1; // Equivalent to multiplying by 2 |
| 67 | + } |
| 68 | + |
| 69 | + Ok(if number > 1 { power >> 1 } else { 1 }) |
| 70 | +} |
| 71 | + |
| 72 | +#[cfg(test)] |
| 73 | +mod tests { |
| 74 | + use super::*; |
| 75 | + |
| 76 | + #[test] |
| 77 | + fn test_zero() { |
| 78 | + assert_eq!(find_previous_power_of_two(0).unwrap(), 0); |
| 79 | + } |
| 80 | + |
| 81 | + #[test] |
| 82 | + fn test_one() { |
| 83 | + assert_eq!(find_previous_power_of_two(1).unwrap(), 1); |
| 84 | + } |
| 85 | + |
| 86 | + #[test] |
| 87 | + fn test_powers_of_two() { |
| 88 | + assert_eq!(find_previous_power_of_two(2).unwrap(), 2); |
| 89 | + assert_eq!(find_previous_power_of_two(4).unwrap(), 4); |
| 90 | + assert_eq!(find_previous_power_of_two(8).unwrap(), 8); |
| 91 | + assert_eq!(find_previous_power_of_two(16).unwrap(), 16); |
| 92 | + assert_eq!(find_previous_power_of_two(32).unwrap(), 32); |
| 93 | + assert_eq!(find_previous_power_of_two(64).unwrap(), 64); |
| 94 | + assert_eq!(find_previous_power_of_two(128).unwrap(), 128); |
| 95 | + assert_eq!(find_previous_power_of_two(256).unwrap(), 256); |
| 96 | + assert_eq!(find_previous_power_of_two(512).unwrap(), 512); |
| 97 | + assert_eq!(find_previous_power_of_two(1024).unwrap(), 1024); |
| 98 | + } |
| 99 | + |
| 100 | + #[test] |
| 101 | + fn test_numbers_between_powers() { |
| 102 | + // Between 2 and 4 |
| 103 | + assert_eq!(find_previous_power_of_two(3).unwrap(), 2); |
| 104 | + |
| 105 | + // Between 4 and 8 |
| 106 | + assert_eq!(find_previous_power_of_two(5).unwrap(), 4); |
| 107 | + assert_eq!(find_previous_power_of_two(6).unwrap(), 4); |
| 108 | + assert_eq!(find_previous_power_of_two(7).unwrap(), 4); |
| 109 | + |
| 110 | + // Between 8 and 16 |
| 111 | + assert_eq!(find_previous_power_of_two(9).unwrap(), 8); |
| 112 | + assert_eq!(find_previous_power_of_two(10).unwrap(), 8); |
| 113 | + assert_eq!(find_previous_power_of_two(11).unwrap(), 8); |
| 114 | + assert_eq!(find_previous_power_of_two(12).unwrap(), 8); |
| 115 | + assert_eq!(find_previous_power_of_two(13).unwrap(), 8); |
| 116 | + assert_eq!(find_previous_power_of_two(14).unwrap(), 8); |
| 117 | + assert_eq!(find_previous_power_of_two(15).unwrap(), 8); |
| 118 | + |
| 119 | + // Between 16 and 32 |
| 120 | + assert_eq!(find_previous_power_of_two(17).unwrap(), 16); |
| 121 | + assert_eq!(find_previous_power_of_two(20).unwrap(), 16); |
| 122 | + assert_eq!(find_previous_power_of_two(31).unwrap(), 16); |
| 123 | + } |
| 124 | + |
| 125 | + #[test] |
| 126 | + fn test_range_0_to_17() { |
| 127 | + // Test the exact output from the Python docstring |
| 128 | + let expected = vec![0, 1, 2, 2, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16]; |
| 129 | + let results: Vec<u32> = (0..18) |
| 130 | + .map(|i| find_previous_power_of_two(i).unwrap()) |
| 131 | + .collect(); |
| 132 | + assert_eq!(results, expected); |
| 133 | + } |
| 134 | + |
| 135 | + #[test] |
| 136 | + fn test_large_numbers() { |
| 137 | + assert_eq!(find_previous_power_of_two(100).unwrap(), 64); |
| 138 | + assert_eq!(find_previous_power_of_two(500).unwrap(), 256); |
| 139 | + assert_eq!(find_previous_power_of_two(1000).unwrap(), 512); |
| 140 | + assert_eq!(find_previous_power_of_two(2000).unwrap(), 1024); |
| 141 | + assert_eq!(find_previous_power_of_two(10000).unwrap(), 8192); |
| 142 | + } |
| 143 | + |
| 144 | + #[test] |
| 145 | + fn test_max_safe_values() { |
| 146 | + assert_eq!(find_previous_power_of_two(1023).unwrap(), 512); |
| 147 | + assert_eq!(find_previous_power_of_two(2047).unwrap(), 1024); |
| 148 | + assert_eq!(find_previous_power_of_two(4095).unwrap(), 2048); |
| 149 | + } |
| 150 | + |
| 151 | + #[test] |
| 152 | + fn test_negative_number_returns_error() { |
| 153 | + let result = find_previous_power_of_two(-1); |
| 154 | + assert!(result.is_err()); |
| 155 | + assert_eq!(result.unwrap_err(), "Input must be a non-negative integer"); |
| 156 | + } |
| 157 | + |
| 158 | + #[test] |
| 159 | + fn test_negative_numbers_return_errors() { |
| 160 | + assert!(find_previous_power_of_two(-5).is_err()); |
| 161 | + assert!(find_previous_power_of_two(-10).is_err()); |
| 162 | + assert!(find_previous_power_of_two(-100).is_err()); |
| 163 | + } |
| 164 | + |
| 165 | + #[test] |
| 166 | + fn test_edge_cases() { |
| 167 | + // One less than powers of two |
| 168 | + assert_eq!(find_previous_power_of_two(127).unwrap(), 64); |
| 169 | + assert_eq!(find_previous_power_of_two(255).unwrap(), 128); |
| 170 | + assert_eq!(find_previous_power_of_two(511).unwrap(), 256); |
| 171 | + } |
| 172 | +} |
0 commit comments