diff options
Diffstat (limited to 'src/day_5.rs')
| -rw-r--r-- | src/day_5.rs | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/src/day_5.rs b/src/day_5.rs new file mode 100644 index 0000000..acd2ac1 --- /dev/null +++ b/src/day_5.rs @@ -0,0 +1,125 @@ +use std::cmp; +use std::convert::Infallible; +use std::str::FromStr; + +const SIZE: usize = 1000; + +#[derive(Debug)] +struct Line +{ + pub a: (u32, u32), + pub b: (u32, u32), +} + +fn part1(input: &[Line]) +{ + let mut map = [[0; SIZE]; SIZE]; + for line in input { + line.cast_vh(&mut map); + } + + let num_intersections = map.iter().flatten().filter(|&n| *n >= 2).count(); + println!("Solution part 1: {}", num_intersections); +} + +fn part2(input: &[Line]) +{ + let mut map = [[0; SIZE]; SIZE]; + for line in input { + line.cast_vh(&mut map); + line.cast_diag(&mut map); + } + + let num_intersections = map.iter().flatten().filter(|&n| *n >= 2).count(); + println!("Solution part 2: {}", num_intersections); +} + +pub fn run(input: Vec<String>) +{ + let lines: Vec<Line> = input.iter().map(|s| Line::from_str(s).unwrap()).collect(); + + part1(&lines); + part2(&lines); +} + +impl Line +{ + pub fn is_horizontal(&self) -> bool { self.a.1 == self.b.1 } + + pub fn is_vertical(&self) -> bool { self.a.0 == self.b.0 } + + pub fn cast_vh(&self, onto: &mut [[u8; SIZE]]) + { + if self.is_horizontal() { + let start = cmp::min(self.a.0, self.b.0); + let end = cmp::max(self.a.0, self.b.0); + for x in start..=end { + onto[self.a.1 as usize][x as usize] += 1; + } + } + else if self.is_vertical() { + let start = cmp::min(self.a.1, self.b.1); + let end = cmp::max(self.a.1, self.b.1); + for y in start..=end { + onto[y as usize][self.a.0 as usize] += 1; + } + } + } + + pub fn cast_diag(&self, onto: &mut [[u8; SIZE]]) + { + if self.is_horizontal() || self.is_vertical() { + return; + } + + // We know all other lines are 45 deg + let mut dir = (0, 0); + let len: i32 = if self.a.0 < self.b.0 { + dir.0 = 1; + (self.b.0 - self.a.0) as i32 + } + else if self.a.0 > self.b.0 { + dir.0 = -1; + (self.a.0 - self.b.0) as i32 + } + else { + panic!("line is unexpectedly vertical!"); + }; + if self.a.1 < self.b.1 { + dir.1 = 1; + } + else if self.a.1 > self.b.1 { + dir.1 = -1; + } + else { + panic!("line is unexpectedly horizontal!"); + } + + for i in 0..=len { + onto[(self.a.1 as i32 + (i * dir.1)) as usize] + [(self.a.0 as i32 + (i * dir.0)) as usize] += 1; + } + } +} + +impl FromStr for Line +{ + type Err = Infallible; + + fn from_str(s: &str) -> Result<Self, Self::Err> + { + let parse_point = |s: &str| { + let nums: Vec<u32> = s.split(',').map(|s| s.parse().unwrap()).collect(); + assert_eq!(nums.len(), 2); + (nums[0], nums[1]) + }; + + let points: Vec<(u32, u32)> = s.split(" -> ").map(|s| parse_point(s)).collect(); + assert_eq!(points.len(), 2); + + Ok(Line { + a: points[0], + b: points[1], + }) + } +} |
