From d28af3f66f64f0c0ccac7b269313d0761c771011 Mon Sep 17 00:00:00 2001 From: EFanZh Date: Sun, 4 Aug 2024 20:36:06 +0800 Subject: [PATCH] Add problem 2013: Detect Squares --- src/lib.rs | 1 + src/problem_2013_detect_squares/hash_map.rs | 85 +++ src/problem_2013_detect_squares/mod.rs | 586 ++++++++++++++++++++ 3 files changed, 672 insertions(+) create mode 100644 src/problem_2013_detect_squares/hash_map.rs create mode 100644 src/problem_2013_detect_squares/mod.rs diff --git a/src/lib.rs b/src/lib.rs index 6ee93f20..73658a56 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1487,6 +1487,7 @@ pub mod problem_2007_find_original_array_from_doubled_array; pub mod problem_2008_maximum_earnings_from_taxi; pub mod problem_2011_final_value_of_variable_after_performing_operations; pub mod problem_2012_sum_of_beauty_in_the_array; +pub mod problem_2013_detect_squares; pub mod problem_2016_maximum_difference_between_increasing_elements; pub mod problem_2017_grid_game; pub mod problem_2018_check_if_word_can_be_placed_in_crossword; diff --git a/src/problem_2013_detect_squares/hash_map.rs b/src/problem_2013_detect_squares/hash_map.rs new file mode 100644 index 00000000..7c75ab11 --- /dev/null +++ b/src/problem_2013_detect_squares/hash_map.rs @@ -0,0 +1,85 @@ +// ------------------------------------------------------ snip ------------------------------------------------------ // + +use std::collections::hash_map::Entry; +use std::collections::HashMap; + +pub struct DetectSquares { + points: HashMap>, +} + +impl DetectSquares { + fn new() -> Self { + Self { points: HashMap::new() } + } + + fn add(&mut self, point: Vec) { + let [x, y]: [_; 2] = point.try_into().ok().unwrap(); + let x = x as u16; + let y = y as u16; + + match self.points.entry(x) { + Entry::Occupied(entry) => match entry.into_mut().entry(y) { + Entry::Occupied(entry) => *entry.into_mut() += 1, + Entry::Vacant(entry) => { + entry.insert(1); + } + }, + Entry::Vacant(entry) => { + entry.insert(HashMap::from([(y, 1)])); + } + } + } + + fn count(&self, point: Vec) -> i32 { + let [x_0, y_0]: [_; 2] = point.try_into().ok().unwrap(); + let x_0 = x_0 as u16; + let y_0 = y_0 as u16; + let mut result = 0; + + if let Some(column_0) = self.points.get(&x_0) { + for (&y_1, &count_0) in column_0 { + if y_0 == y_1 { + continue; + } + + let d = y_1.wrapping_sub(y_0); + + for x_1 in [x_0.wrapping_sub(d), x_0.wrapping_add(d)] { + if let Some(column_1) = self.points.get(&x_1) { + if let Some(&count_1) = column_1.get(&y_0) { + if let Some(&count_2) = column_1.get(&y_1) { + result += u32::from(count_0) * u32::from(count_1) * u32::from(count_2); + } + } + } + } + } + } + + result as _ + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::DetectSquares for DetectSquares { + fn new() -> Self { + Self::new() + } + + fn add(&mut self, point: Vec) { + self.add(point); + } + + fn count(&self, point: Vec) -> i32 { + self.count(point) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2013_detect_squares/mod.rs b/src/problem_2013_detect_squares/mod.rs new file mode 100644 index 00000000..cb5f081f --- /dev/null +++ b/src/problem_2013_detect_squares/mod.rs @@ -0,0 +1,586 @@ +pub mod hash_map; + +pub trait DetectSquares { + fn new() -> Self; + fn add(&mut self, point: Vec); + fn count(&self, point: Vec) -> i32; +} + +#[cfg(test)] +mod tests { + use super::DetectSquares; + + enum Operation { + Add([i32; 2]), + Count([i32; 2], i32), + } + + const EXTRA_TEST_CASE: &[Operation] = &[ + Operation::Add([5, 10]), + Operation::Add([10, 5]), + Operation::Add([10, 10]), + Operation::Count([5, 5], 1), + Operation::Add([3, 0]), + Operation::Add([8, 0]), + Operation::Add([8, 5]), + Operation::Count([3, 5], 1), + Operation::Add([9, 0]), + Operation::Add([9, 8]), + Operation::Add([1, 8]), + Operation::Count([1, 0], 1), + Operation::Add([0, 0]), + Operation::Add([8, 0]), + Operation::Add([8, 8]), + Operation::Count([0, 8], 2), + Operation::Add([1, 9]), + Operation::Add([2, 9]), + Operation::Add([2, 10]), + Operation::Count([1, 10], 1), + Operation::Add([7, 8]), + Operation::Add([2, 3]), + Operation::Add([2, 8]), + Operation::Count([7, 3], 1), + Operation::Add([9, 10]), + Operation::Add([9, 5]), + Operation::Add([4, 5]), + Operation::Count([4, 10], 1), + Operation::Add([0, 9]), + Operation::Add([4, 5]), + Operation::Add([4, 9]), + Operation::Count([0, 5], 2), + Operation::Add([1, 10]), + Operation::Add([10, 1]), + Operation::Add([10, 10]), + Operation::Count([1, 1], 2), + Operation::Add([10, 0]), + Operation::Add([2, 0]), + Operation::Add([2, 8]), + Operation::Count([10, 8], 2), + Operation::Add([7, 6]), + Operation::Add([4, 6]), + Operation::Add([4, 9]), + Operation::Count([7, 9], 2), + Operation::Add([10, 9]), + Operation::Add([10, 0]), + Operation::Add([1, 0]), + Operation::Count([1, 9], 5), + Operation::Add([0, 9]), + Operation::Add([8, 1]), + Operation::Add([0, 1]), + Operation::Count([8, 9], 6), + Operation::Add([3, 9]), + Operation::Add([10, 9]), + Operation::Add([3, 2]), + Operation::Count([10, 2], 2), + Operation::Add([3, 8]), + Operation::Add([9, 2]), + Operation::Add([3, 2]), + Operation::Count([9, 8], 3), + Operation::Add([0, 9]), + Operation::Add([7, 9]), + Operation::Add([0, 2]), + Operation::Count([7, 2], 3), + Operation::Add([10, 1]), + Operation::Add([1, 10]), + Operation::Add([10, 10]), + Operation::Count([1, 1], 14), + Operation::Add([6, 10]), + Operation::Add([2, 6]), + Operation::Add([6, 6]), + Operation::Count([2, 10], 3), + Operation::Add([6, 0]), + Operation::Add([6, 2]), + Operation::Add([8, 2]), + Operation::Count([8, 0], 1), + Operation::Add([6, 5]), + Operation::Add([7, 4]), + Operation::Add([6, 4]), + Operation::Count([7, 5], 2), + Operation::Add([2, 10]), + Operation::Add([8, 4]), + Operation::Add([2, 4]), + Operation::Count([8, 10], 2), + Operation::Add([2, 6]), + Operation::Add([2, 5]), + Operation::Add([1, 5]), + Operation::Count([1, 6], 4), + Operation::Add([10, 9]), + Operation::Add([10, 0]), + Operation::Add([1, 9]), + Operation::Count([1, 0], 20), + Operation::Add([0, 9]), + Operation::Add([5, 9]), + Operation::Add([0, 4]), + Operation::Count([5, 4], 4), + Operation::Add([3, 6]), + Operation::Add([9, 0]), + Operation::Add([3, 0]), + Operation::Count([9, 6], 5), + Operation::Add([0, 2]), + Operation::Add([1, 1]), + Operation::Add([0, 1]), + Operation::Count([1, 2], 10), + Operation::Add([1, 7]), + Operation::Add([8, 0]), + Operation::Add([8, 7]), + Operation::Count([1, 0], 26), + Operation::Add([2, 7]), + Operation::Add([4, 5]), + Operation::Add([2, 5]), + Operation::Count([4, 7], 8), + Operation::Add([6, 7]), + Operation::Add([3, 7]), + Operation::Add([6, 4]), + Operation::Count([3, 4], 3), + Operation::Add([10, 2]), + Operation::Add([2, 10]), + Operation::Add([2, 2]), + Operation::Count([10, 10], 7), + Operation::Add([10, 1]), + Operation::Add([1, 10]), + Operation::Add([1, 1]), + Operation::Count([10, 10], 21), + Operation::Add([2, 10]), + Operation::Add([2, 9]), + Operation::Add([3, 9]), + Operation::Count([3, 10], 20), + Operation::Add([10, 1]), + Operation::Add([1, 10]), + Operation::Add([1, 1]), + Operation::Count([10, 10], 52), + Operation::Add([10, 4]), + Operation::Add([10, 3]), + Operation::Add([9, 4]), + Operation::Count([9, 3], 6), + Operation::Add([6, 6]), + Operation::Add([6, 10]), + Operation::Add([10, 6]), + Operation::Count([10, 10], 56), + Operation::Add([9, 7]), + Operation::Add([4, 7]), + Operation::Add([9, 2]), + Operation::Count([4, 2], 2), + Operation::Add([2, 3]), + Operation::Add([2, 1]), + Operation::Add([0, 3]), + Operation::Count([0, 1], 5), + Operation::Add([2, 8]), + Operation::Add([10, 8]), + Operation::Add([2, 0]), + Operation::Count([10, 0], 17), + Operation::Add([8, 4]), + Operation::Add([2, 10]), + Operation::Add([8, 10]), + Operation::Count([2, 4], 18), + Operation::Add([0, 0]), + Operation::Add([9, 9]), + Operation::Add([0, 9]), + Operation::Count([9, 0], 13), + Operation::Add([5, 7]), + Operation::Add([5, 8]), + Operation::Add([4, 7]), + Operation::Count([4, 8], 19), + Operation::Add([10, 10]), + Operation::Add([10, 1]), + Operation::Add([1, 1]), + Operation::Count([1, 10], 102), + Operation::Add([6, 8]), + Operation::Add([7, 8]), + Operation::Add([6, 9]), + Operation::Count([7, 9], 9), + Operation::Add([4, 6]), + Operation::Add([1, 6]), + Operation::Add([4, 3]), + Operation::Count([1, 3], 2), + Operation::Add([10, 1]), + Operation::Add([1, 10]), + Operation::Add([10, 10]), + Operation::Count([1, 1], 157), + Operation::Add([7, 7]), + Operation::Add([7, 10]), + Operation::Add([4, 7]), + Operation::Count([4, 10], 23), + Operation::Add([0, 0]), + Operation::Add([8, 0]), + Operation::Add([0, 8]), + Operation::Count([8, 8], 29), + Operation::Add([3, 5]), + Operation::Add([2, 4]), + Operation::Add([3, 4]), + Operation::Count([2, 5], 23), + Operation::Add([0, 6]), + Operation::Add([0, 2]), + Operation::Add([4, 2]), + Operation::Count([4, 6], 15), + Operation::Add([5, 2]), + Operation::Add([9, 6]), + Operation::Add([9, 2]), + Operation::Count([5, 6], 24), + Operation::Add([1, 1]), + Operation::Add([1, 10]), + Operation::Add([10, 10]), + Operation::Count([10, 1], 186), + Operation::Add([7, 5]), + Operation::Add([2, 0]), + Operation::Add([2, 5]), + Operation::Count([7, 0], 12), + Operation::Add([1, 9]), + Operation::Add([1, 2]), + Operation::Add([8, 2]), + Operation::Count([8, 9], 32), + Operation::Add([3, 8]), + Operation::Add([3, 3]), + Operation::Add([8, 3]), + Operation::Count([8, 8], 36), + Operation::Add([3, 10]), + Operation::Add([9, 10]), + Operation::Add([3, 4]), + Operation::Count([9, 4], 10), + Operation::Add([0, 2]), + Operation::Add([0, 10]), + Operation::Add([8, 10]), + Operation::Count([8, 2], 35), + Operation::Add([9, 4]), + Operation::Add([8, 4]), + Operation::Add([8, 5]), + Operation::Count([9, 5], 20), + Operation::Add([9, 8]), + Operation::Add([4, 3]), + Operation::Add([4, 8]), + Operation::Count([9, 3], 43), + Operation::Add([4, 9]), + Operation::Add([0, 5]), + Operation::Add([0, 9]), + Operation::Count([4, 5], 48), + Operation::Add([1, 3]), + Operation::Add([3, 5]), + Operation::Add([1, 5]), + Operation::Count([3, 3], 35), + Operation::Add([0, 0]), + Operation::Add([0, 8]), + Operation::Add([8, 0]), + Operation::Count([8, 8], 73), + Operation::Add([2, 8]), + Operation::Add([10, 0]), + Operation::Add([10, 8]), + Operation::Count([2, 0], 59), + Operation::Add([8, 1]), + Operation::Add([0, 9]), + Operation::Add([8, 9]), + Operation::Count([0, 1], 56), + Operation::Add([4, 9]), + Operation::Add([4, 6]), + Operation::Add([1, 9]), + Operation::Count([1, 6], 72), + Operation::Add([0, 9]), + Operation::Add([0, 8]), + Operation::Add([1, 9]), + Operation::Count([1, 8], 198), + Operation::Add([5, 1]), + Operation::Add([5, 6]), + Operation::Add([10, 1]), + Operation::Count([10, 6], 37), + Operation::Add([9, 2]), + Operation::Add([2, 2]), + Operation::Add([2, 9]), + Operation::Count([9, 9], 145), + Operation::Add([5, 5]), + Operation::Add([8, 5]), + Operation::Add([5, 8]), + Operation::Count([8, 8], 130), + Operation::Add([8, 0]), + Operation::Add([1, 0]), + Operation::Add([8, 7]), + Operation::Count([1, 7], 45), + Operation::Add([8, 2]), + Operation::Add([5, 5]), + Operation::Add([5, 2]), + Operation::Count([8, 5], 68), + Operation::Add([6, 6]), + Operation::Add([6, 8]), + Operation::Add([8, 6]), + Operation::Count([8, 8], 172), + Operation::Add([2, 10]), + Operation::Add([10, 2]), + Operation::Add([2, 2]), + Operation::Count([10, 10], 281), + Operation::Add([1, 9]), + Operation::Add([8, 2]), + Operation::Add([1, 2]), + Operation::Count([8, 9], 147), + Operation::Add([7, 4]), + Operation::Add([7, 2]), + Operation::Add([9, 4]), + Operation::Count([9, 2], 53), + Operation::Add([1, 9]), + Operation::Add([1, 0]), + Operation::Add([10, 0]), + Operation::Count([10, 9], 160), + Operation::Add([2, 10]), + Operation::Add([2, 3]), + Operation::Add([9, 10]), + Operation::Count([9, 3], 105), + Operation::Add([10, 0]), + Operation::Add([1, 0]), + Operation::Add([1, 9]), + Operation::Count([10, 9], 253), + Operation::Add([8, 10]), + Operation::Add([1, 10]), + Operation::Add([1, 3]), + Operation::Count([8, 3], 82), + Operation::Add([0, 9]), + Operation::Add([9, 9]), + Operation::Add([0, 0]), + Operation::Count([9, 0], 103), + Operation::Add([7, 9]), + Operation::Add([8, 9]), + Operation::Add([7, 8]), + Operation::Count([8, 8], 248), + Operation::Add([3, 1]), + Operation::Add([9, 7]), + Operation::Add([9, 1]), + Operation::Count([3, 7], 75), + Operation::Add([5, 9]), + Operation::Add([6, 9]), + Operation::Add([5, 8]), + Operation::Count([6, 8], 86), + Operation::Add([0, 1]), + Operation::Add([0, 10]), + Operation::Add([9, 10]), + Operation::Count([9, 1], 312), + Operation::Add([8, 0]), + Operation::Add([8, 2]), + Operation::Add([10, 2]), + Operation::Count([10, 0], 301), + Operation::Add([8, 0]), + Operation::Add([0, 8]), + Operation::Add([8, 8]), + Operation::Count([0, 0], 273), + Operation::Add([6, 7]), + Operation::Add([5, 8]), + Operation::Add([5, 7]), + Operation::Count([6, 8], 119), + Operation::Add([0, 9]), + Operation::Add([0, 2]), + Operation::Add([7, 9]), + Operation::Count([7, 2], 191), + Operation::Add([5, 0]), + Operation::Add([5, 5]), + Operation::Add([10, 0]), + Operation::Count([10, 5], 61), + Operation::Add([1, 10]), + Operation::Add([10, 10]), + Operation::Add([10, 1]), + Operation::Count([1, 1], 584), + Operation::Add([9, 2]), + Operation::Add([9, 10]), + Operation::Add([1, 2]), + Operation::Count([1, 10], 696), + Operation::Add([1, 10]), + Operation::Add([10, 1]), + Operation::Add([10, 10]), + Operation::Count([1, 1], 802), + Operation::Add([9, 9]), + Operation::Add([0, 9]), + Operation::Add([0, 0]), + Operation::Count([9, 0], 293), + Operation::Add([9, 6]), + Operation::Add([9, 3]), + Operation::Add([6, 3]), + Operation::Count([6, 6], 104), + Operation::Add([10, 4]), + Operation::Add([6, 0]), + Operation::Add([10, 0]), + Operation::Count([6, 4], 114), + Operation::Add([6, 8]), + Operation::Add([0, 2]), + Operation::Add([0, 8]), + Operation::Count([6, 2], 242), + Operation::Add([7, 9]), + Operation::Add([0, 9]), + Operation::Add([7, 2]), + Operation::Count([0, 2], 259), + Operation::Add([9, 1]), + Operation::Add([9, 10]), + Operation::Add([0, 10]), + Operation::Count([0, 1], 300), + Operation::Add([10, 0]), + Operation::Add([10, 9]), + Operation::Add([1, 9]), + Operation::Count([1, 0], 465), + Operation::Add([1, 6]), + Operation::Add([1, 9]), + Operation::Add([4, 9]), + Operation::Count([4, 6], 180), + Operation::Add([0, 8]), + Operation::Add([1, 9]), + Operation::Add([0, 9]), + Operation::Count([1, 8], 1082), + Operation::Add([1, 1]), + Operation::Add([9, 1]), + Operation::Add([1, 9]), + Operation::Count([9, 9], 697), + Operation::Add([2, 5]), + Operation::Add([2, 9]), + Operation::Add([6, 5]), + Operation::Count([6, 9], 187), + Operation::Add([7, 3]), + Operation::Add([2, 3]), + Operation::Add([2, 8]), + Operation::Count([7, 8], 113), + Operation::Add([9, 4]), + Operation::Add([4, 4]), + Operation::Add([9, 9]), + Operation::Count([4, 9], 201), + Operation::Add([4, 4]), + Operation::Add([2, 4]), + Operation::Add([4, 2]), + Operation::Count([2, 2], 520), + Operation::Add([0, 3]), + Operation::Add([0, 2]), + Operation::Add([1, 3]), + Operation::Count([1, 2], 652), + Operation::Add([10, 9]), + Operation::Add([10, 2]), + Operation::Add([3, 2]), + Operation::Count([3, 9], 197), + Operation::Add([5, 6]), + Operation::Add([10, 6]), + Operation::Add([10, 1]), + Operation::Count([5, 1], 91), + Operation::Add([9, 0]), + Operation::Add([0, 9]), + Operation::Add([9, 9]), + Operation::Count([0, 0], 670), + Operation::Add([5, 6]), + Operation::Add([9, 2]), + Operation::Add([9, 6]), + Operation::Count([5, 2], 159), + Operation::Add([3, 3]), + Operation::Add([10, 3]), + Operation::Add([10, 10]), + Operation::Count([3, 10], 189), + Operation::Add([2, 4]), + Operation::Add([2, 10]), + Operation::Add([8, 4]), + Operation::Count([8, 10], 386), + Operation::Add([4, 9]), + Operation::Add([1, 9]), + Operation::Add([4, 6]), + Operation::Count([1, 6], 403), + Operation::Add([1, 8]), + Operation::Add([9, 0]), + Operation::Add([1, 0]), + Operation::Count([9, 8], 204), + Operation::Add([10, 3]), + Operation::Add([5, 8]), + Operation::Add([5, 3]), + Operation::Count([10, 8], 301), + Operation::Add([8, 2]), + Operation::Add([0, 10]), + Operation::Add([8, 10]), + Operation::Count([0, 2], 378), + Operation::Add([9, 0]), + Operation::Add([2, 7]), + Operation::Add([9, 7]), + Operation::Count([2, 0], 314), + Operation::Add([0, 4]), + Operation::Add([5, 9]), + Operation::Add([0, 9]), + Operation::Count([5, 4], 292), + Operation::Add([5, 3]), + Operation::Add([10, 3]), + Operation::Add([5, 8]), + Operation::Count([10, 8], 352), + Operation::Add([6, 4]), + Operation::Add([7, 4]), + Operation::Add([6, 5]), + Operation::Count([7, 5], 174), + Operation::Add([9, 1]), + Operation::Add([0, 1]), + Operation::Add([9, 10]), + Operation::Count([0, 10], 2778), + Operation::Add([5, 10]), + Operation::Add([5, 7]), + Operation::Add([8, 7]), + Operation::Count([8, 10], 473), + Operation::Add([8, 0]), + Operation::Add([8, 7]), + Operation::Add([1, 7]), + Operation::Count([1, 0], 869), + Operation::Add([1, 1]), + Operation::Add([9, 9]), + Operation::Add([1, 9]), + Operation::Count([9, 1], 1568), + Operation::Add([3, 1]), + Operation::Add([3, 5]), + Operation::Add([7, 5]), + Operation::Count([7, 1], 190), + Operation::Add([5, 8]), + Operation::Add([5, 3]), + Operation::Add([10, 8]), + Operation::Count([10, 3], 198), + Operation::Add([0, 9]), + Operation::Add([2, 7]), + Operation::Add([2, 9]), + Operation::Count([0, 7], 342), + Operation::Add([9, 3]), + Operation::Add([9, 7]), + Operation::Add([5, 3]), + Operation::Count([5, 7], 286), + Operation::Add([0, 0]), + Operation::Add([9, 0]), + Operation::Add([9, 9]), + Operation::Count([0, 9], 1062), + Operation::Add([6, 4]), + Operation::Add([4, 2]), + Operation::Add([4, 4]), + Operation::Count([6, 2], 475), + Operation::Add([1, 9]), + Operation::Add([1, 5]), + Operation::Add([5, 5]), + Operation::Count([5, 9], 354), + Operation::Add([7, 7]), + Operation::Add([0, 7]), + Operation::Add([0, 0]), + Operation::Count([7, 0], 174), + Operation::Add([1, 3]), + Operation::Add([1, 9]), + Operation::Add([7, 3]), + Operation::Count([7, 9], 574), + Operation::Add([0, 9]), + Operation::Add([9, 9]), + Operation::Add([9, 0]), + Operation::Count([0, 0], 1605), + Operation::Add([1, 8]), + Operation::Add([3, 6]), + Operation::Add([3, 8]), + Operation::Count([1, 6], 547), + ]; + + pub fn run() { + let test_cases = [ + &[ + Operation::Add([3, 10]), + Operation::Add([11, 2]), + Operation::Add([3, 2]), + Operation::Count([11, 10], 1), + Operation::Count([14, 8], 0), + Operation::Add([11, 2]), + Operation::Count([11, 10], 2), + ] as &[_], + EXTRA_TEST_CASE, + ]; + + for operations in test_cases { + let mut detect_square = D::new(); + + for operation in operations { + match *operation { + Operation::Add(point) => detect_square.add(point.to_vec()), + Operation::Count(point, expected) => assert_eq!(detect_square.count(point.to_vec()), expected), + } + } + } + } +}