Challenge 61
Find Peaks and Valleys
Given an immutable array of integers, identify peaks (elements strictly greater than both neighbors) and valleys (elements strictly less than both neighbors). Elements at the very beginning or end of the array (which only have one neighbor) cannot be peaks or valleys.
Your task is to return a Vec<usize>
containing the 0-indexed positions of all peaks and valleys in the array. The returned indices should be sorted in ascending order.
Write your solution below
// Rust Bytes Issue 69: Find Peaks and Valleys pub fn find_peaks_and_valleys(arr: &[i64]) -> Vec<usize> { // your implementation goes here } #[cfg(test)] mod tests { use super::*; #[test] fn test_example_1_corrected() { let arr = vec![1, 2, 1, 3, 4, 5, 4, 3, 2, 1, 2, 3]; assert_eq!(find_peaks_and_valleys(&arr), vec![1, 2, 5, 9]); } #[test] fn test_example_2_flat() { let arr = vec![1, 1, 1, 1, 1]; assert_eq!(find_peaks_and_valleys(&arr), vec![]); } #[test] fn test_example_3_mixed() { let arr = vec![10, 5, 20, 15, 30, 25]; assert_eq!(find_peaks_and_valleys(&arr), vec![1, 2, 3, 4]); } #[test] fn test_example_4_single_element() { let arr = vec![5]; assert_eq!(find_peaks_and_valleys(&arr), vec![]); } #[test] fn test_example_5_two_elements() { let arr = vec![5, 1]; assert_eq!(find_peaks_and_valleys(&arr), vec![]); } #[test] fn test_empty_array() { let arr: Vec<i64> = vec![]; assert_eq!(find_peaks_and_valleys(&arr), vec![]); } #[test] fn test_long_alternating_pattern() { let arr = vec![1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; assert_eq!(find_peaks_and_valleys(&arr), vec![1, 2, 3, 4, 5, 6, 7, 8]); } #[test] fn test_plateau_then_peak() { let arr = vec![1, 2, 2, 2, 3, 1]; assert_eq!(find_peaks_and_valleys(&arr), vec![4]); } #[test] fn test_peak_then_plateau() { let arr = vec![1, 3, 2, 2, 2, 1]; assert_eq!(find_peaks_and_valleys(&arr), vec![1]); } #[test] fn test_negative_numbers() { let arr = vec![-5, -10, -7, -15, -12]; assert_eq!(find_peaks_and_valleys(&arr), vec![1, 2, 3]); } }
Solution
Click to Show/Hide Solution
#![allow(unused)] fn main() { // Rust Bytes Issue 69: Find Peaks and Valleys pub fn find_peaks_and_valleys(arr: &[i64]) -> Vec<usize> { // your implementation goes here arr.windows(3) .enumerate() .filter_map(|(index, window)| { let (l_n, item, r_n) = (window[0], window[1], window[2]); if (item > l_n && item > r_n) || (item < l_n && item < r_n) { Some(index + 1) } else { None } }) .collect() } #[cfg(test)] mod tests { use super::*; #[test] fn test_example_1_corrected() { let arr = vec![1, 2, 1, 3, 4, 5, 4, 3, 2, 1, 2, 3]; assert_eq!(find_peaks_and_valleys(&arr), vec![1, 2, 5, 9]); } #[test] fn test_example_2_flat() { let arr = vec![1, 1, 1, 1, 1]; assert_eq!(find_peaks_and_valleys(&arr), vec![]); } #[test] fn test_example_3_mixed() { let arr = vec![10, 5, 20, 15, 30, 25]; assert_eq!(find_peaks_and_valleys(&arr), vec![1, 2, 3, 4]); } #[test] fn test_example_4_single_element() { let arr = vec![5]; assert_eq!(find_peaks_and_valleys(&arr), vec![]); } #[test] fn test_example_5_two_elements() { let arr = vec![5, 1]; assert_eq!(find_peaks_and_valleys(&arr), vec![]); } #[test] fn test_empty_array() { let arr: Vec<i64> = vec![]; assert_eq!(find_peaks_and_valleys(&arr), vec![]); } #[test] fn test_long_alternating_pattern() { let arr = vec![1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; assert_eq!(find_peaks_and_valleys(&arr), vec![1, 2, 3, 4, 5, 6, 7, 8]); } #[test] fn test_plateau_then_peak() { let arr = vec![1, 2, 2, 2, 3, 1]; assert_eq!(find_peaks_and_valleys(&arr), vec![4]); } #[test] fn test_peak_then_plateau() { let arr = vec![1, 3, 2, 2, 2, 1]; assert_eq!(find_peaks_and_valleys(&arr), vec![1]); } #[test] fn test_negative_numbers() { let arr = vec![-5, -10, -7, -15, -12]; assert_eq!(find_peaks_and_valleys(&arr), vec![1, 2, 3]); } } }