From f31c1aa3a08acf152d862fef86724ead026d9312 Mon Sep 17 00:00:00 2001 From: Thomas Heslin <13917706+tjheslin1@users.noreply.github.com> Date: Sat, 18 Dec 2021 08:41:49 +0000 Subject: [PATCH] Handle diagonal lines --- 2021/day5/src/main.rs | 5 +- 2021/day5/src/vents.rs | 133 ++++++++++++++++++++++++++++++----------- 2 files changed, 103 insertions(+), 35 deletions(-) diff --git a/2021/day5/src/main.rs b/2021/day5/src/main.rs index dc124a0..18769b6 100644 --- a/2021/day5/src/main.rs +++ b/2021/day5/src/main.rs @@ -6,7 +6,10 @@ fn main() { let input = fs::read_to_string("input.txt").expect("Something went wrong reading the file"); let lines = vents::parse_input(&input[..]); - let overlap_count = vents::find_overlapping_points(&lines[..], 2); + let overlap_count = vents::find_overlapping_points(&lines[..], 2, false); println!("overlap_count = {}", overlap_count); + + let diagonal_overlap_count = vents::find_overlapping_points(&lines[..], 2, true); + println!("diagonal overlap_count = {}", diagonal_overlap_count); } diff --git a/2021/day5/src/vents.rs b/2021/day5/src/vents.rs index db32e36..bb2bbb8 100644 --- a/2021/day5/src/vents.rs +++ b/2021/day5/src/vents.rs @@ -5,12 +5,16 @@ use itertools::Itertools; type Point = (usize, usize); type Line = (usize, usize, usize, usize); -pub fn find_overlapping_points(lines: &[Line], min_overlap: usize) -> usize { +pub fn find_overlapping_points(lines: &[Line], min_overlap: usize, handle_diagonal: bool) -> usize { let mut overlaps: Vec = vec![]; for first in 0..lines.len() { for second in first + 1..lines.len() { - overlaps.append(&mut lines_overlap(&lines[first], &lines[second])); + overlaps.append(&mut lines_overlap( + &lines[first], + &lines[second], + handle_diagonal, + )); } } @@ -39,17 +43,15 @@ pub fn parse_input(input: &str) -> Vec { .collect::>() } -fn lines_overlap(first: &Line, second: &Line) -> Vec { +fn lines_overlap(first: &Line, second: &Line, handle_diagonal: bool) -> Vec { let (first_x_1, first_y_1, first_x_2, first_y_2) = *first; let (second_x_1, second_y_1, second_x_2, second_y_2) = *second; - // if diagonal - if first_x_1 != first_x_2 && first_y_1 != first_y_2 { + if handle_diagonal == false && first_x_1 != first_x_2 && first_y_1 != first_y_2 { return vec![]; } - // if diagonal - if second_x_1 != second_x_2 && second_y_1 != second_y_2 { + if handle_diagonal == false && second_x_1 != second_x_2 && second_y_1 != second_y_2 { return vec![]; } @@ -64,28 +66,26 @@ fn lines_overlap(first: &Line, second: &Line) -> Vec { } fn find_points(x_1: usize, y_1: usize, x_2: usize, y_2: usize) -> Vec { - let mut points: Vec = vec![]; - - let min_x = cmp::min(x_1, x_2); - let max_x = cmp::max(x_1, x_2); - - let min_y = cmp::min(y_1, y_2); - let max_y = cmp::max(y_1, y_2); - - let mut x = min_x; - let mut y = min_y; - while x <= max_x { - while y <= max_y { - points.push((x, y)); - - y += 1; - } - - x += 1; - y = min_y; - } - - points + let x_length = i32::abs((x_1 as i32) - (x_2 as i32)) as usize; + let y_length = i32::abs((y_1 as i32) - (y_2 as i32)) as usize; + + let x_range = match x_length { + 0 => vec![x_1; y_length + 1], + _ if x_1 <= x_2 => (x_1..=x_2).collect::>(), + _ => (x_2..=x_1).rev().collect::>(), + }; + + let y_range = match y_length { + 0 => vec![y_1; x_length + 1], + _ if y_1 <= y_2 => (y_1..=y_2).collect::>(), + _ => (y_2..=y_1).rev().collect::>(), + }; + + x_range + .iter() + .zip(y_range.iter()) + .map(|(x, y)| (*x, *y)) + .collect::>() } #[cfg(test)] @@ -138,11 +138,31 @@ mod tests { (5, 5, 8, 2), ]; - let actual_num_overlapping_points = find_overlapping_points(&input_points[..], 2); + let actual_num_overlapping_points = find_overlapping_points(&input_points[..], 2, false); assert_eq!(actual_num_overlapping_points, 5); } + #[test] + fn test_find_overlapping_points_diagonal_example() { + let input_points = vec![ + (0, 9, 5, 9), + (8, 0, 0, 8), + (9, 4, 3, 4), + (2, 2, 2, 1), + (7, 0, 7, 4), + (6, 4, 2, 0), + (0, 9, 2, 9), + (3, 4, 1, 4), + (0, 0, 8, 8), + (5, 5, 8, 2), + ]; + + let actual_num_overlapping_points = find_overlapping_points(&input_points[..], 2, true); + + assert_eq!(actual_num_overlapping_points, 12); + } + /* 1......... 1......... @@ -171,6 +191,34 @@ mod tests { assert_eq!(actual, expected); } + /* + 1......... + .1........ + ..1....... + .......... + */ + #[test] + fn test_find_points_diagonal() { + let actual = find_points(0, 0, 2, 2); + let expected = vec![(0, 0), (1, 1), (2, 2)]; + + assert_eq!(actual, expected); + } + + /* + ..1....... + .1........ + 1......... + .......... + */ + #[test] + fn test_find_points_diagonal_back() { + let actual = find_points(2, 0, 0, 2); + let expected = vec![(2, 0), (1, 1), (0, 2)]; + + assert_eq!(actual, expected); + } + /* 1.1....... 1.1....... @@ -182,7 +230,7 @@ mod tests { let first = (0, 0, 0, 2); let second = (2, 0, 2, 2); - let actual = lines_overlap(&first, &second); + let actual = lines_overlap(&first, &second, false); let expected = vec![]; assert_eq!(actual, expected); @@ -199,7 +247,7 @@ mod tests { let first = (0, 0, 0, 2); let second = (0, 1, 3, 1); - let actual = lines_overlap(&first, &second); + let actual = lines_overlap(&first, &second, false); let expected = vec![(0, 1)]; assert_eq!(actual, expected); @@ -216,7 +264,7 @@ mod tests { let first = (0, 0, 2, 0); let second = (2, 0, 2, 2); - let actual = lines_overlap(&first, &second); + let actual = lines_overlap(&first, &second, false); let expected = vec![(2, 0)]; assert_eq!(actual, expected); @@ -233,9 +281,26 @@ mod tests { let first = (2, 0, 2, 2); let second = (2, 0, 2, 1); - let actual = lines_overlap(&first, &second); + let actual = lines_overlap(&first, &second, false); let expected = vec![(2, 0), ((2, 1))]; assert_eq!(actual, expected); } + + /* + 1.1....... + .2........ + 1.1....... + .......... + */ + #[test] + fn test_do_lines_overlap_diagonals() { + let first = (2, 0, 0, 2); + let second = (0, 0, 2, 2); + + let actual = lines_overlap(&first, &second, true); + let expected = vec![(1, 1)]; + + assert_eq!(actual, expected); + } }