summaryrefslogtreecommitdiff
path: root/src/day_5.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/day_5.rs')
-rw-r--r--src/day_5.rs125
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],
+ })
+ }
+}