1use std::cmp::Ordering;
30
31pub trait OrdVec<T: PartialOrd> {
33 fn push_ord_ascending(&mut self, item: T) -> Result<usize, OrdVecError>;
50 fn push_ord_descending(&mut self, item: T) -> Result<usize, OrdVecError>;
67}
68
69impl<T: PartialOrd> OrdVec<T> for Vec<T> {
70 fn push_ord_ascending(&mut self, item: T) -> Result<usize, OrdVecError> {
71 let idx = binary_search_index_ascending(&item, self);
72 match idx {
73 Some(idx) => {
74 self.insert(idx, item);
75 Ok(idx)
76 }
77 None => Err(OrdVecError),
78 }
79 }
80
81 fn push_ord_descending(&mut self, item: T) -> Result<usize, OrdVecError> {
82 let idx = binary_search_index_descending(&item, self);
83 match idx {
84 Some(idx) => {
85 self.insert(idx, item);
86 Ok(idx)
87 }
88 None => Err(OrdVecError),
89 }
90 }
91}
92
93#[derive(Debug, PartialEq, Eq)]
95pub struct OrdVecError;
96
97impl std::fmt::Display for OrdVecError {
98 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
99 write!(f, "Failed to add item to vector")
100 }
101}
102
103impl std::error::Error for OrdVecError {}
104
105#[inline]
107fn mid_point(a: usize, b: usize) -> usize {
108 (a + b) / 2
109}
110
111#[inline]
113fn binary_search_index_ascending<T: PartialOrd>(item: &T, values: &[T]) -> Option<usize> {
114 if values.is_empty() {
115 return Some(0);
116 }
117 let mut start: usize = 0;
118 let mut end = values.len() - 1;
119 if item <= &values[start] {
120 return Some(start);
121 }
122
123 if item >= &values[end] {
124 return Some(end + 1);
125 }
126 let mut idx: usize = mid_point(start, end);
127 loop {
128 match item.partial_cmp(&values[idx]) {
129 Some(Ordering::Less) => {
130 end = idx;
131 idx = mid_point(start, end);
132 if end - start <= 1 {
133 idx = end;
134 break;
135 }
136 }
137 Some(Ordering::Greater) => {
138 start = idx;
139 idx = mid_point(start, end);
140 if end - start <= 1 {
141 idx = end;
142 break;
143 }
144 }
145 Some(Ordering::Equal) => {
146 break;
147 }
148 None => {
149 return None;
150 }
151 }
152 }
153 Some(idx)
154}
155
156#[inline]
157fn binary_search_index_descending<T: PartialOrd>(item: &T, values: &[T]) -> Option<usize> {
158 if values.is_empty() {
159 return Some(0);
160 }
161 let mut start: usize = 0;
162 let mut end = values.len() - 1;
163 if item >= &values[start] {
164 return Some(start);
165 }
166
167 if item <= &values[end] {
168 return Some(end + 1);
169 }
170 let mut idx: usize = mid_point(start, end);
171 loop {
172 match item.partial_cmp(&values[idx]) {
173 Some(Ordering::Less) => {
174 start = idx;
175 idx = mid_point(start, end);
176 if end - start <= 1 {
177 idx = end;
178 break;
179 }
180 }
181 Some(Ordering::Greater) => {
182 end = idx;
183 idx = mid_point(start, end);
184 if end - start <= 1 {
185 idx = end;
186 break;
187 }
188 }
189 Some(Ordering::Equal) => {
190 break;
191 }
192 None => {
193 return None;
194 }
195 }
196 }
197 Some(idx)
198}
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203
204 #[test]
205 fn test_mid_point() {
206 for i in 0..100 {
207 assert_eq!(mid_point(0, i), i / 2);
208 }
209 }
210
211 #[test]
212 fn test_binary_search_index_ascending() {
213 let values_1 = [1, 2, 3, 4, 5];
214 assert_eq!(binary_search_index_ascending(&4, &values_1), Some(3));
215 assert_eq!(binary_search_index_ascending(&6, &values_1), Some(5));
216 assert_eq!(binary_search_index_ascending(&0, &values_1), Some(0));
217
218 let values_2 = ["apple", "banana", "cherry", "date", "elderberry"];
219 assert_eq!(binary_search_index_ascending(&"cherry", &values_2), Some(2));
220 assert_eq!(binary_search_index_ascending(&"fig", &values_2), Some(5));
221 assert_eq!(
222 binary_search_index_ascending(&"apricot", &values_2),
223 Some(1)
224 );
225 assert_eq!(
226 binary_search_index_ascending(&"aardvark", &values_2),
227 Some(0)
228 );
229
230 let values_3 = [1.5, 2.7, 3.1, 4.9, 5.2];
231 assert_eq!(binary_search_index_ascending(&2.7, &values_3), Some(1));
232 assert_eq!(binary_search_index_ascending(&3.15, &values_3), Some(3));
233 assert_eq!(binary_search_index_ascending(&1.0, &values_3), Some(0));
234
235 let values_4 = [1, 2, 3, 4];
236 assert_eq!(binary_search_index_ascending(&5, &values_4), Some(4));
237 assert_eq!(binary_search_index_ascending(&0, &values_4), Some(0));
238 }
239
240 #[test]
241 fn test_binary_search_index_descending() {
242 let values = [4, 3, 2, 1];
243 assert_eq!(binary_search_index_descending(&1, &values), Some(4));
244 assert_eq!(binary_search_index_descending(&2, &values), Some(2));
245 assert_eq!(binary_search_index_descending(&3, &values), Some(1));
246 assert_eq!(binary_search_index_descending(&4, &values), Some(0));
247 assert_eq!(binary_search_index_descending(&5, &values), Some(0));
248 assert_eq!(binary_search_index_descending(&0, &values), Some(4));
249 let values = [4., 3., 2., 1.];
250 assert_eq!(binary_search_index_descending(&2.5, &values), Some(2));
251
252 let values = [1];
253 assert_eq!(binary_search_index_descending(&1, &values), Some(0));
254 assert_eq!(binary_search_index_descending(&0, &values), Some(1));
255 assert_eq!(binary_search_index_descending(&2, &values), Some(0));
256
257 let values = [];
258 assert_eq!(binary_search_index_descending(&1, &values), Some(0));
259 assert_eq!(binary_search_index_descending(&0, &values), Some(0));
260 assert_eq!(binary_search_index_descending(&2, &values), Some(0));
261
262 let values = ["elderberry", "date", "cherry", "banana", "apple"];
263 assert_eq!(binary_search_index_descending(&"cherry", &values), Some(2));
264 assert_eq!(binary_search_index_descending(&"fig", &values), Some(0));
265 assert_eq!(binary_search_index_descending(&"apricot", &values), Some(4));
266 assert_eq!(
267 binary_search_index_descending(&"aardvark", &values),
268 Some(5)
269 );
270 assert_eq!(
271 binary_search_index_descending(&"elderberry", &values),
272 Some(0)
273 );
274 assert_eq!(binary_search_index_descending(&"apple", &values), Some(5));
275
276 let values_2 = [5.2, 4.9, 3.1, 2.7, 1.5];
277 assert_eq!(binary_search_index_descending(&2.7, &values_2), Some(3));
278 assert_eq!(binary_search_index_descending(&3.15, &values_2), Some(2));
279 assert_eq!(binary_search_index_descending(&1.0, &values_2), Some(5));
280 }
281
282 #[test]
283 fn test_ord_vec_ascending() {
284 let mut values: Vec<i32> = Vec::new();
285
286 assert_eq!(values.push_ord_ascending(5), Ok(0));
287 assert_eq!(values, [5]);
288
289 assert_eq!(values.push_ord_ascending(3), Ok(0));
290 assert_eq!(values, [3, 5]);
291
292 assert_eq!(values.push_ord_ascending(7), Ok(2));
293 assert_eq!(values, [3, 5, 7]);
294
295 assert_eq!(values.push_ord_ascending(1), Ok(0));
296 assert_eq!(values, [1, 3, 5, 7]);
297
298 assert_eq!(values.push_ord_ascending(9), Ok(4));
299 assert_eq!(values, [1, 3, 5, 7, 9]);
300
301 assert_eq!(values.push_ord_ascending(8), Ok(4));
302 assert_eq!(values, [1, 3, 5, 7, 8, 9]);
303
304 assert_eq!(values.push_ord_ascending(100), Ok(6));
305 assert_eq!(values, [1, 3, 5, 7, 8, 9, 100]);
306
307 assert_eq!(values.push_ord_ascending(3), Ok(1));
308 assert_eq!(values, [1, 3, 3, 5, 7, 8, 9, 100]);
309
310 assert_eq!(values.push_ord_ascending(2), Ok(1));
311 assert_eq!(values, [1, 2, 3, 3, 5, 7, 8, 9, 100]);
312
313 assert_eq!(values.push_ord_ascending(0), Ok(0));
314 assert_eq!(values, [0, 1, 2, 3, 3, 5, 7, 8, 9, 100]);
315 }
316
317 #[test]
318 fn test_ord_vec_descending() {
319 let mut values: Vec<i32> = Vec::new();
320
321 assert_eq!(values.push_ord_descending(5), Ok(0));
322 assert_eq!(values, [5]);
323
324 assert_eq!(values.push_ord_descending(3), Ok(1));
325 assert_eq!(values, [5, 3]);
326
327 assert_eq!(values.push_ord_descending(7), Ok(0));
328 assert_eq!(values, [7, 5, 3]);
329
330 assert_eq!(values.push_ord_descending(1), Ok(3));
331 assert_eq!(values, [7, 5, 3, 1]);
332
333 assert_eq!(values.push_ord_descending(9), Ok(0));
334 assert_eq!(values, [9, 7, 5, 3, 1]);
335
336 assert_eq!(values.push_ord_descending(8), Ok(1));
337 assert_eq!(values, [9, 8, 7, 5, 3, 1]);
338
339 assert_eq!(values.push_ord_descending(100), Ok(0));
340 assert_eq!(values, [100, 9, 8, 7, 5, 3, 1]);
341
342 assert_eq!(values.push_ord_descending(3), Ok(5));
343 assert_eq!(values, [100, 9, 8, 7, 5, 3, 3, 1]);
344
345 assert_eq!(values.push_ord_descending(2), Ok(7));
346 assert_eq!(values, [100, 9, 8, 7, 5, 3, 3, 2, 1]);
347
348 assert_eq!(values.push_ord_descending(0), Ok(9));
349 assert_eq!(values, [100, 9, 8, 7, 5, 3, 3, 2, 1, 0]);
350 }
351}