between_us/
interface.rs

1use std::cmp::Ordering;
2///```
3/// use between_us::interface::find_distance;
4///
5/// let list = [5, 3, 7, 1, 6, 8, 4];
6///
7/// let result = find_distance(&list);
8/// 
9/// println!("{:?}", result);
10/// ```
11pub fn find_distance(list: &[u32]) -> Option<usize> {
12	let mut smaller_idx_list: Vec<usize> = Vec::with_capacity(list.len());
13
14	let mut smallest_idx_now = 0;
15
16	smaller_idx_list.push(smallest_idx_now);
17
18	// Collects the next smaller elements
19	for idx in 1..list.len() {
20		if list[idx] < list[smallest_idx_now] {
21			smallest_idx_now = idx;
22			smaller_idx_list.push(smallest_idx_now);
23		}
24	}
25
26	// Let rightmost idx be the idx of biggest number for now
27	let mut idx_of_biggest = list.len() - 1;
28
29	// Set the march point on idx of biggest number
30	let mut march_idx = idx_of_biggest;
31
32	let mut max_distance_now: Option<usize> = None;
33
34	for small_idx in smaller_idx_list.iter().rev() {
35		// Stop when search for bigger idx marches past the small idx
36		while march_idx > *small_idx {
37			// Compare the value at this idx with current biggest number
38			match list[march_idx].cmp(&list[idx_of_biggest]) {
39				Ordering::Equal => (),
40				Ordering::Greater => idx_of_biggest = march_idx,
41				Ordering::Less => {
42					// March backwards
43					march_idx -= 1;
44					continue;
45				}
46			}
47
48			if list[idx_of_biggest] > list[*small_idx] {
49				let distance_now = idx_of_biggest - *small_idx;
50
51				match max_distance_now {
52					Some(val) => {
53						// if current distance > prev max distance, assigns current distance to max distance.
54						if distance_now > val {
55							max_distance_now = Some(distance_now);
56						}
57					}
58					// if max distance is `None`, assigns current distance.
59					None => max_distance_now = Some(distance_now),
60				}
61
62				break;
63			} else {
64				march_idx -= 1;
65			}
66		}
67	}
68
69	max_distance_now
70}