use num_traits::Num;
pub fn find_min_max<T>(x: &[T]) -> (usize, usize)
where
T: Num + PartialOrd,
{
let n = x.len();
match n {
0 => (usize::MAX, usize::MAX),
1 => (0, 0),
_ => {
let mut index_min = 0;
let mut index_max = 0;
for i in 1..n {
if x[i] < x[index_min] {
index_min = i;
} else if x[i] > x[index_max] {
index_max = i;
}
}
(index_min, index_max)
}
}
}
#[cfg(test)]
mod tests {
use super::find_min_max;
#[test]
fn find_min_max_works() {
let (min, max) = find_min_max(&[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]);
assert_eq!(min, 1);
assert_eq!(max, 5);
}
#[test]
fn find_min_max_empty_slice() {
let empty: &[i32] = &[];
let (min, max) = find_min_max(empty);
assert_eq!(min, usize::MAX);
assert_eq!(max, usize::MAX);
}
#[test]
fn find_min_max_single_element() {
let (min, max) = find_min_max(&[42]);
assert_eq!(min, 0);
assert_eq!(max, 0);
}
#[test]
fn find_min_max_two_elements_ascending() {
let (min, max) = find_min_max(&[1, 5]);
assert_eq!(min, 0);
assert_eq!(max, 1);
}
#[test]
fn find_min_max_two_elements_descending() {
let (min, max) = find_min_max(&[8, 3]);
assert_eq!(min, 1);
assert_eq!(max, 0);
}
#[test]
fn find_min_max_two_equal_elements() {
let (min, max) = find_min_max(&[7, 7]);
assert_eq!(min, 0);
assert_eq!(max, 0);
}
#[test]
fn find_min_max_all_equal_elements() {
let (min, max) = find_min_max(&[5, 5, 5, 5, 5]);
assert_eq!(min, 0);
assert_eq!(max, 0);
}
#[test]
fn find_min_max_negative_numbers() {
let (min, max) = find_min_max(&[-3.0, -1.0, -4.0, -1.0, -5.0]);
assert_eq!(min, 4); assert_eq!(max, 1); }
#[test]
fn find_min_max_mixed_positive_negative() {
let (min, max) = find_min_max(&[-2, 5, -8, 10, 1]);
assert_eq!(min, 2); assert_eq!(max, 3); }
#[test]
fn find_min_max_zeros() {
let (min, max) = find_min_max(&[0, 0, 0]);
assert_eq!(min, 0);
assert_eq!(max, 0);
}
#[test]
fn find_min_max_with_zeros_and_others() {
let (min, max) = find_min_max(&[3, 0, -1, 2, 0]);
assert_eq!(min, 2); assert_eq!(max, 0);
let (min, max) = find_min_max(&[f64::EPSILON, f64::EPSILON, f64::EPSILON]);
assert_eq!(min, 0);
assert_eq!(max, 0);
let (min, max) = find_min_max(&[f64::EPSILON, 0.0, f64::EPSILON]);
assert_eq!(min, 1); assert_eq!(max, 0);
}
#[test]
fn find_min_max_first_occurrence_priority() {
let (min, max) = find_min_max(&[2, 1, 3, 1, 3, 2]);
assert_eq!(min, 1); assert_eq!(max, 2); }
#[test]
fn find_min_max_min_at_end() {
let (min, max) = find_min_max(&[5, 4, 3, 2, 1]);
assert_eq!(min, 4); assert_eq!(max, 0); }
#[test]
fn find_min_max_max_at_end() {
let (min, max) = find_min_max(&[1, 2, 3, 4, 5]);
assert_eq!(min, 0); assert_eq!(max, 4); }
#[test]
fn find_min_max_alternating() {
let (min, max) = find_min_max(&[1, 10, 2, 9, 3, 8]);
assert_eq!(min, 0); assert_eq!(max, 1); }
#[test]
fn find_min_max_floating_point() {
let (min, max) = find_min_max(&[3.14, 2.71, 1.41, 2.71, 3.14]);
assert_eq!(min, 2); assert_eq!(max, 0); }
#[test]
fn find_min_max_very_small_floats() {
let (min, max) = find_min_max(&[1e-10, 1e-15, 1e-5, 1e-20]);
assert_eq!(min, 3); assert_eq!(max, 2); }
#[test]
fn find_min_max_large_numbers() {
let values = [1_000_000, 999_999, 1_000_001, 999_998];
let (min, max) = find_min_max(&values);
assert_eq!(min, 3); assert_eq!(max, 2); }
#[test]
fn find_min_max_u8_type() {
let (min, max) = find_min_max(&[100u8, 50u8, 200u8, 25u8]);
assert_eq!(min, 3); assert_eq!(max, 2); }
#[test]
fn find_min_max_i64_type() {
let values: &[i64] = &[i64::MAX, i64::MIN, 0, -1, 1];
let (min, max) = find_min_max(values);
assert_eq!(min, 1); assert_eq!(max, 0); }
#[test]
fn find_min_max_same_min_max_at_ends() {
let (min, max) = find_min_max(&[1, 5, 3, 7, 2, 10]);
assert_eq!(min, 0); assert_eq!(max, 5); }
#[test]
fn find_min_max_plateau_pattern() {
let (min, max) = find_min_max(&[1, 1, 1, 5, 5, 5, 2, 2, 2]);
assert_eq!(min, 0); assert_eq!(max, 3); }
#[test]
fn find_min_max_mountain_pattern() {
let (min, max) = find_min_max(&[1, 2, 3, 4, 5, 4, 3, 2, 1]);
assert_eq!(min, 0); assert_eq!(max, 4); }
#[test]
fn find_min_max_valley_pattern() {
let (min, max) = find_min_max(&[5, 4, 3, 2, 1, 2, 3, 4, 5]);
assert_eq!(min, 4); assert_eq!(max, 0); }
#[test]
fn find_min_max_repeated_extremes() {
let (min, max) = find_min_max(&[1, 5, 1, 3, 5, 1, 5]);
assert_eq!(min, 0); assert_eq!(max, 1); }
}