1use core::cmp::{Ord, Ordering, PartialEq};
2
3use num::{Float, Num, NumCast};
4
5use crate::ext::cmp;
6
7pub fn average<T>(data: Vec<T>) -> Option<T>
9where
10 T: Num,
11{
12 let mut sum = T::zero();
13 let mut count = T::zero();
14 for v in data {
15 sum = sum + v;
16 count = count + T::one();
17 }
18 if count == T::zero() {
19 None
20 } else {
21 Some(sum / count)
22 }
23}
24
25pub fn median_by<T, F>(mut data: Vec<T>, compare: F) -> Option<T>
27where
28 T: Num + NumCast,
29 F: FnMut(&T, &T) -> Ordering,
30{
31 if data.is_empty() {
32 return None;
33 }
34
35 data.sort_by(compare);
36 let mid = data.len() / 2;
37 if data.len() % 2 == 0 {
38 let rhs = data.swap_remove(mid);
39 let lhs = data.swap_remove(mid - 1);
40 Some((lhs + rhs) / NumCast::from(2).unwrap())
41 } else {
42 Some(data.swap_remove(mid))
43 }
44}
45
46pub fn median_integer<T>(data: Vec<T>) -> Option<T>
48where
49 T: Ord + Num + NumCast,
50{
51 median_by(data, T::cmp)
52}
53
54pub fn median_float<T>(data: Vec<T>) -> Option<T>
56where
57 T: Float + NumCast,
58{
59 median_by(data, cmp::fcmp)
60}
61
62pub fn majority<T>(mut data: Vec<T>) -> Option<T>
64where
65 T: PartialEq,
66{
67 let mut candidate = 0;
68 let mut count = 1;
69 let len = data.len();
70
71 for idx in 1..len {
74 if data[candidate] == data[idx] {
75 count += 1;
76 } else {
77 count -= 1;
78 }
79 if count == 0 {
80 candidate = idx;
81 count = 1;
82 }
83 }
84
85 count = 0;
86 for idx in 0..len {
87 if data[candidate] == data[idx] {
88 count += 1;
89 }
90 }
91
92 if 2 * count > len {
93 Some(data.swap_remove(candidate))
94 } else {
95 None
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn test_average_empty() {
105 let vals: Vec<i64> = vec![];
106 assert_eq!(average(vals), None);
107 }
108
109 #[test]
110 fn test_average_int() {
111 let vals = vec![3, 2, 5, 7, 2, 9, 1];
112 assert_eq!(average(vals), Some(4));
113 }
114
115 #[test]
116 fn test_average_single_int() {
117 let vals = vec![3];
118 assert_eq!(average(vals), Some(3));
119 }
120
121 #[test]
122 fn test_average_float() {
123 let vals = vec![3.0, 2.0, 5.0, 7.0, 2.0, 9.0, 1.0];
124 assert_eq!(average(vals), Some(4.142857142857143));
125 }
126
127 #[test]
128 fn test_average_single_float() {
129 let vals = vec![3.0];
130 assert_eq!(average(vals), Some(3.0));
131 }
132
133 #[test]
134 fn test_median_odd_int() {
135 let vals = vec![3, 2, 5, 7, 2, 9, 1];
136 assert_eq!(median_integer(vals), Some(3));
137 }
138
139 #[test]
140 fn test_median_single_int() {
141 let vals = vec![3];
142 assert_eq!(median_integer(vals), Some(3));
143 }
144
145 #[test]
146 fn test_median_empty() {
147 let vals: Vec<i64> = vec![];
148 assert_eq!(median_integer(vals), None);
149 }
150
151 #[test]
152 fn test_median_even_int() {
153 let vals = vec![3, 2, 5, 7, 2, 10, 32, 1];
154 assert_eq!(median_integer(vals), Some(4));
155 let vals = vec![13, 36, 33, 45];
156 assert_eq!(median_integer(vals), Some(34));
157 let vals = vec![13, 15];
158 assert_eq!(median_integer(vals), Some(14));
159 }
160
161 #[test]
162 fn test_median_odd_float() {
163 let vals = vec![3.5, 2.7, 5.1, 7.4, 2.0, 9.1, 1.9];
164 assert_eq!(median_float(vals), Some(3.5));
165 }
166
167 #[test]
168 fn test_median_single_float() {
169 let vals = vec![3.0];
170 assert_eq!(median_float(vals), Some(3.0));
171 }
172
173 #[test]
174 fn test_median_even_float() {
175 let vals = vec![3.4, 2.0, 5.7, 7.1, 2.2, 10.1, 32.0, 1.8];
176 assert_eq!(median_float(vals), Some(4.55));
177 let vals = vec![13.0, 36.0, 45.0, 33.0];
178 assert_eq!(median_float(vals), Some(34.5));
179 let vals = vec![13.0, 36.2];
180 assert_eq!(median_float(vals), Some(24.6));
181 }
182
183 #[test]
184 fn test_majority_int() {
185 let vals = vec![1, 2, 3, 1, 3, 1, 1];
186 assert_eq!(majority(vals), Some(1));
187 }
188
189 #[test]
190 fn test_majority_single_int() {
191 let vals = vec![3];
192 assert_eq!(majority(vals), Some(3));
193 }
194
195 #[test]
196 fn test_majority_int_result_none() {
197 let vals = vec![1, 2, 3, 1, 3, 1, 1, 3];
198 assert_eq!(majority(vals), None);
199 }
200
201 #[test]
202 fn test_majority_float() {
203 let vals = vec![0.3, 1.0, 0.3, 0.4, 1.0, 1.0, 1.0];
204 assert_eq!(majority(vals), Some(1.0));
205 }
206
207 #[test]
208 fn test_majority_single_float() {
209 let vals = vec![3.0];
210 assert_eq!(majority(vals), Some(3.0));
211 }
212
213 #[test]
214 fn test_majority_float_result_none() {
215 let vals = vec![0.3, 1.0, 0.3, 0.4, 4.0, 1.0, 99.99, 1.0, 1.0];
216 assert_eq!(majority(vals), None);
217 }
218
219 #[test]
220 fn test_majority_char() {
221 let vals = vec!['a', 'b', 'a', 'b', 'b'];
222 assert_eq!(majority(vals), Some('b'));
223 }
224
225 #[test]
226 fn test_majority_single_char() {
227 let vals = vec!['a'];
228 assert_eq!(majority(vals), Some('a'));
229 }
230
231 #[test]
232 fn test_majority_char_result_none() {
233 let vals = vec!['a', 'b', 'a', 'b', 'c', 'b'];
234 assert_eq!(majority(vals), None);
235 }
236
237 #[test]
238 fn test_majority_string() {
239 let vals = vec![String::from("mumu"), String::from("mumu"), String::from("momo")];
240 assert_eq!(majority(vals), Some(String::from("mumu")));
241 }
242
243 #[test]
244 fn test_majority_single_string() {
245 let vals = vec![String::from("mumu")];
246 assert_eq!(majority(vals), Some(String::from("mumu")));
247 }
248
249 #[test]
250 fn test_majority_string_result_none() {
251 let vals = vec![String::from("mumu"), String::from("momo")];
252 assert_eq!(majority(vals), None);
253 }
254}