competitive/tools/
comparator.rs

1use 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}