Advent of Code solutions
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at db70ca7fa220d0320b47036e7aa38273645acd18 172 lines 4.7 kB view raw
1use std::{fmt::Debug, ops::Range}; 2 3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 4/// Represents a range of values. 5/// 6/// End is exclusive. 7pub struct BetterRange<T: Copy + Clone + Debug> { 8 pub start: T, 9 pub end: T, 10} 11 12impl<T: Copy + Clone + Debug> BetterRange<T> { 13 pub fn new(start: T, end: T) -> Self { 14 Self { start, end } 15 } 16} 17 18pub enum RangeSplitBehavior { 19 IncludeLower, 20 IncludeUpper, 21 Exclude, 22} 23 24impl<T: Copy + Clone + Debug + Ord> BetterRange<T> { 25 /// Checks if the range contains the given value. 26 /// 27 /// # Examples 28 /// 29 /// ``` 30 /// use utils::prelude::*; 31 /// 32 /// let range = BetterRange::new(0, 10); 33 /// assert!(range.contains(&5)); 34 /// assert!(!range.contains(&10)); 35 /// ``` 36 /// 37 pub fn contains(&self, value: &T) -> bool { 38 self.start <= *value && *value < self.end 39 } 40 41 /// Checks if the range contains the given range. 42 /// 43 /// # Examples 44 /// 45 /// ``` 46 /// use utils::prelude::*; 47 /// 48 /// let range = BetterRange::new(0, 10); 49 /// assert!(range.contains_range(&BetterRange::new(5, 7))); 50 /// assert!(!range.contains_range(&BetterRange::new(5, 15))); 51 /// ``` 52 /// 53 pub fn contains_range(&self, other: &Self) -> bool { 54 self.start <= other.start && other.end < self.end 55 } 56 57 /// Split the range at the given value. 58 /// 59 /// The behaviour determines if the value is included in the lower range, upper range, or neither. 60 /// 61 /// # Examples 62 /// 63 /// ``` 64 /// use utils::prelude::*; 65 /// 66 /// let range = BetterRange::new(0, 10); 67 /// 68 /// let (lower, upper) = range.split(&5, RangeSplitBehavior::IncludeLower); 69 /// assert_eq!(lower, Some(BetterRange::new(0, 6))); 70 /// assert_eq!(upper, Some(BetterRange::new(6, 10))); 71 /// ``` 72 /// 73 /// ``` 74 /// use utils::prelude::*; 75 /// 76 /// let range = BetterRange::new(0, 10); 77 /// 78 /// let (lower, upper) = range.split(&5, RangeSplitBehavior::IncludeUpper); 79 /// assert_eq!(lower, Some(BetterRange::new(0, 5))); 80 /// assert_eq!(upper, Some(BetterRange::new(5, 10))); 81 /// ``` 82 /// 83 /// ``` 84 /// use utils::prelude::*; 85 /// 86 /// let range = BetterRange::new(0, 10); 87 /// 88 /// let (lower, upper) = range.split(&5, RangeSplitBehavior::Exclude); 89 /// assert_eq!(lower, Some(BetterRange::new(0, 5))); 90 /// assert_eq!(upper, Some(BetterRange::new(6, 10))); 91 /// ``` 92 /// 93 pub fn split(&self, value: &T, behaviour: RangeSplitBehavior) -> (Option<Self>, Option<Self>) 94 where 95 T: std::ops::Add<usize, Output = T> + std::ops::Sub<usize, Output = T>, 96 { 97 if self.contains(value) { 98 match behaviour { 99 RangeSplitBehavior::IncludeLower => ( 100 Some(Self::new(self.start, *value + 1)), 101 Some(Self::new(*value + 1, self.end)), 102 ), 103 RangeSplitBehavior::IncludeUpper => ( 104 Some(Self::new(self.start, *value)), 105 Some(Self::new(*value, self.end)), 106 ), 107 RangeSplitBehavior::Exclude => ( 108 Some(Self::new(self.start, *value)), 109 Some(Self::new(*value + 1, self.end)), 110 ), 111 } 112 } else { 113 (None, None) 114 } 115 } 116} 117 118impl<T: Copy + Clone + Debug + Ord> From<BetterRange<T>> for Range<T> { 119 fn from(val: BetterRange<T>) -> Self { 120 val.start..val.end 121 } 122} 123 124impl<T: Copy + Clone + Debug + Ord> From<Range<T>> for BetterRange<T> { 125 fn from(val: Range<T>) -> Self { 126 BetterRange::new(val.start, val.end) 127 } 128} 129 130impl<T: Copy + Clone + Debug + Ord> std::ops::Add<usize> for BetterRange<T> 131where 132 T: std::ops::Add<usize, Output = T>, 133{ 134 type Output = Self; 135 136 fn add(self, rhs: usize) -> Self::Output { 137 Self::new(self.start + rhs, self.end + rhs) 138 } 139} 140 141impl<T: Copy + Clone + Debug + Ord> std::ops::Sub<usize> for BetterRange<T> 142where 143 T: std::ops::Sub<usize, Output = T>, 144{ 145 type Output = Self; 146 147 fn sub(self, rhs: usize) -> Self::Output { 148 Self::new(self.start - rhs, self.end - rhs) 149 } 150} 151 152impl<T: Copy + Clone + Debug + Ord> std::ops::BitAnd for BetterRange<T> 153where 154 T: std::ops::BitAnd<Output = T>, 155{ 156 type Output = Self; 157 158 fn bitand(self, rhs: Self) -> Self::Output { 159 Self::new(self.start.max(rhs.start), self.end.min(rhs.end)) 160 } 161} 162 163impl<T: Copy + Clone + Debug + Ord> std::ops::BitOr for BetterRange<T> 164where 165 T: std::ops::BitOr<Output = T>, 166{ 167 type Output = Self; 168 169 fn bitor(self, rhs: Self) -> Self::Output { 170 Self::new(self.start.min(rhs.start), self.end.max(rhs.end)) 171 } 172}