competitive/tools/
comparator.rs1use std::cmp::Ordering;
2
3pub trait Comparator<T> {
4 fn compare(&mut self, a: &T, b: &T) -> Ordering;
5}
6
7impl<T, F> Comparator<T> for F
8where
9 F: FnMut(&T, &T) -> Ordering,
10{
11 fn compare(&mut self, a: &T, b: &T) -> Ordering {
12 (self)(a, b)
13 }
14}
15
16#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
17pub struct Less;
18impl<T> Comparator<T> for Less
19where
20 T: Ord,
21{
22 fn compare(&mut self, a: &T, b: &T) -> Ordering {
23 a.cmp(b)
24 }
25}
26
27#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
28pub struct Greater;
29impl<T> Comparator<T> for Greater
30where
31 T: Ord,
32{
33 fn compare(&mut self, a: &T, b: &T) -> Ordering {
34 b.cmp(a)
35 }
36}
37
38#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
39pub struct ByKey<F>(pub F);
40impl<T, F, K> Comparator<T> for ByKey<F>
41where
42 F: FnMut(&T) -> K,
43 K: Ord,
44{
45 fn compare(&mut self, a: &T, b: &T) -> Ordering {
46 (self.0)(a).cmp(&(self.0)(b))
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn test_fn_comparator() {
56 let mut cmp = |a: &i32, b: &i32| b.cmp(a);
57 assert_eq!(cmp.compare(&1, &2), Ordering::Greater);
58 assert_eq!(cmp.compare(&2, &1), Ordering::Less);
59 assert_eq!(cmp.compare(&1, &1), Ordering::Equal);
60 }
61
62 #[test]
63 fn test_less_comparator() {
64 let mut cmp = Less;
65 assert_eq!(cmp.compare(&1, &2), Ordering::Less);
66 assert_eq!(cmp.compare(&2, &1), Ordering::Greater);
67 assert_eq!(cmp.compare(&1, &1), Ordering::Equal);
68 }
69
70 #[test]
71 fn test_greater_comparator() {
72 let mut cmp = Greater;
73 assert_eq!(cmp.compare(&1, &2), Ordering::Greater);
74 assert_eq!(cmp.compare(&2, &1), Ordering::Less);
75 assert_eq!(cmp.compare(&1, &1), Ordering::Equal);
76 }
77
78 #[test]
79 fn test_by_key_comparator() {
80 let mut cmp = ByKey(|x: &i32| -x);
81 assert_eq!(cmp.compare(&1, &2), Ordering::Greater);
82 assert_eq!(cmp.compare(&2, &1), Ordering::Less);
83 assert_eq!(cmp.compare(&1, &1), Ordering::Equal);
84 }
85}