From 5cd11305e713162259a1dc2697c298d6af591743 Mon Sep 17 00:00:00 2001 From: femshima <49227365+femshima@users.noreply.github.com> Date: Sat, 20 Jan 2024 12:16:59 +0900 Subject: [PATCH] free range order --- crates/jlabel-question/src/position.rs | 70 +++++++++++--------------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/crates/jlabel-question/src/position.rs b/crates/jlabel-question/src/position.rs index 67f3677..820fd87 100644 --- a/crates/jlabel-question/src/position.rs +++ b/crates/jlabel-question/src/position.rs @@ -157,13 +157,8 @@ impl Position for SignedRangePosition { type Range = Range; fn range(&self, ranges: &[&str]) -> Result { - let first = ranges.first().ok_or(ParseError::Empty)?; - let mut range = range_i8(first)?; - for r in ranges[1..].iter() { - let r = range_i8(r)?; - extend_range(&mut range, r)?; - } - Ok(range) + let parsed_ranges = ranges.iter().map(range_i8).collect::, _>>()?; + merge_ranges(parsed_ranges) } fn get<'a>(&self, label: &'a Label) -> Option<&'a Self::Target> { @@ -177,8 +172,8 @@ impl Position for SignedRangePosition { } } -fn range_i8(s: &str) -> Result, ParseError> { - let range = match s { +fn range_i8>(s: S) -> Result, ParseError> { + let range = match s.as_ref() { "-??" => -99..-9, "-?" => -9..0, "?" => 0..10, @@ -240,13 +235,8 @@ impl Position for UnsignedRangePosition { type Range = Range; fn range(&self, ranges: &[&str]) -> Result { - let first = ranges.first().ok_or(ParseError::Empty)?; - let mut range = range_u8(first)?; - for r in ranges[1..].iter() { - let r = range_u8(r)?; - extend_range(&mut range, r)?; - } - Ok(range) + let parsed_ranges = ranges.iter().map(range_u8).collect::, _>>()?; + merge_ranges(parsed_ranges) } fn get<'a>(&self, label: &'a Label) -> Option<&'a Self::Target> { @@ -286,8 +276,8 @@ impl Position for UnsignedRangePosition { } } -fn range_u8(s: &str) -> Result, ParseError> { - let range = match s { +fn range_u8>(s: S) -> Result, ParseError> { + let range = match s.as_ref() { "?" => 1..10, s if s.ends_with('?') => { let d = s[..s.len() - 1] @@ -303,20 +293,22 @@ fn range_u8(s: &str) -> Result, ParseError> { Ok(range) } -fn extend_range( - target: &mut Range, - Range { start, end }: Range, -) -> Result<(), ParseError> +fn merge_ranges(mut ranges: Vec>) -> Result, ParseError> where - Idx: Eq, + Idx: Ord + Copy, { - let ok = target.end == start; - if ok { - target.end = end; - Ok(()) - } else { - Err(ParseError::IncontinuousRange) - } + ranges.sort_unstable_by_key(|range| range.start); + ranges + .into_iter() + .fold(Err(ParseError::Empty), |acc, curr| match acc { + Err(ParseError::Empty) => Ok(curr), + Ok(mut acc) if curr.start <= acc.end => { + acc.start = acc.start.min(curr.start); + acc.end = acc.end.max(curr.end); + Ok(acc) + } + _ => Err(ParseError::IncontinuousRange), + }) } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -473,21 +465,19 @@ mod tests { } #[test] - fn extend_range_1() { - let mut range = -9..-9; - extend_range(&mut range, -9..-6).unwrap(); - assert_eq!(range, -9..-6); - extend_range(&mut range, -6..-3).unwrap(); - assert_eq!(range, -9..-3); - extend_range(&mut range, -3..2).unwrap(); - assert_eq!(range, -9..2); + fn merge_ranges_1() { + assert_eq!(merge_ranges(vec![0..1]), Ok(0..1)); + assert_eq!(merge_ranges(vec![0..1, 1..3]), Ok(0..3)); + assert_eq!(merge_ranges(vec![1..3, 0..1]), Ok(0..3)); + assert_eq!(merge_ranges(vec![0..2, 1..3]), Ok(0..3)); + assert_eq!(merge_ranges(vec![-6..7, 1..3]), Ok(-6..7)); assert_eq!( - extend_range(&mut range, -16..-10), + merge_ranges(vec![0..1, 5..6]), Err(ParseError::IncontinuousRange) ); assert_eq!( - extend_range(&mut range, 1..3), + merge_ranges(vec![3..6, -1..2]), Err(ParseError::IncontinuousRange) ); }