summary refs log tree commit diff
path: root/13/src
diff options
context:
space:
mode:
Diffstat (limited to '13/src')
-rw-r--r--13/src/main.rs151
1 files changed, 151 insertions, 0 deletions
diff --git a/13/src/main.rs b/13/src/main.rs
new file mode 100644
index 0000000..121fae4
--- /dev/null
+++ b/13/src/main.rs
@@ -0,0 +1,151 @@
+use advent_lib::prelude::*;
+
+use std::collections::HashSet;
+
+
+#[derive(Debug,Clone,Copy,PartialEq,Eq)]
+enum Axis {
+  X,
+  Y,
+}
+
+
+fn main() -> Result<()> {
+  let mut args = std::env::args();
+  if args.len() != 2 {
+    eprintln!("Usage: advent input");
+  }
+  let _ = args.next();
+  let filename = args.next().unwrap();
+
+  let input = advent_lib::group_lines_by_blanks(
+    advent_lib::read_lines_file(&filename)?);
+
+  let mut dots: HashSet<(u64,u64)> = HashSet::new();
+  for line in &input[0] {
+    let words: Vec<&str> = line.split(',').collect();
+    let x = words[0].parse::<u64>()?;
+    let y = words[1].parse::<u64>()?;
+    dots.insert((x, y));
+  }
+
+  let mut folds: Vec<(Axis,u64)> = Vec::new();
+  for line in &input[1]{
+    let words: Vec<&str> = line.split(' ').collect();
+    let subwords: Vec<&str> = words[2].split('=').collect();
+    let axis = match subwords[0] {
+      "x" => Axis::X,
+      "y" => Axis::Y,
+      _ => panic!("hm"),
+    };
+    let value = subwords[1].parse::<u64>()?;
+    folds.push((axis, value));
+  }
+
+  let (width, height) = bounds(&dots);
+
+  let mut first_fold = Vec::new();
+  first_fold.push(folds[0].clone());
+
+  let rendering = render(width, height, &dots, &first_fold);
+  println!("{}", rendering.len());
+
+  let rendering = render(width, height, &dots, &folds);
+  let (width, height) = bounds(&rendering);
+  for y in 0 .. height {
+    for x in 0 .. width {
+      if rendering.contains(&(x, y)) {
+        print!("#");
+      } else {
+        print!(".");
+      }
+    }
+    println!("");
+  }
+
+  Ok(())
+}
+
+
+fn bounds(dots: &HashSet<(u64, u64)>) -> (u64, u64) {
+  let mut max_x = None;
+  let mut max_y = None;
+  for (x, y) in dots {
+    max_x = match max_x {
+      None => Some(x),
+      Some(old_x) => if x > old_x {
+        Some(x)
+      } else {
+        Some(old_x)
+      }
+    };
+
+    max_y = match max_y {
+      None => Some(y),
+      Some(old_y) => if y > old_y {
+        Some(y)
+      } else {
+        Some(old_y)
+      }
+    };
+  }
+  let width = max_x.unwrap() + 1;
+  let height = max_y.unwrap() + 1;
+
+  (width, height)
+}
+
+
+fn render(width: u64, height: u64, dots: &HashSet<(u64, u64)>,
+    folds: &Vec<(Axis, u64)>)
+  -> HashSet<(u64, u64)>
+{
+  let mut result = HashSet::new();
+
+  for y in 0 .. height {
+    for x in 0 .. width {
+      if dots.contains(&(x, y)) {
+        let (new_x, new_y) = apply_folds(x, y, folds);
+        result.insert((new_x, new_y));
+      }
+    }
+  }
+
+  result
+}
+
+
+fn apply_folds(x: u64, y: u64, folds: &Vec<(Axis, u64)>) -> (u64, u64) {
+  let mut transformed_x = x;
+  let mut transformed_y = y;
+
+  for fold in folds {
+    let (new_x, new_y) = apply_fold(transformed_x, transformed_y, fold);
+    transformed_x = new_x;
+    transformed_y = new_y;
+  }
+
+  (transformed_x, transformed_y)
+}
+
+
+fn apply_fold(x: u64, y: u64, fold: &(Axis, u64)) -> (u64, u64) {
+  let (axis, fold_value) = fold;
+  match axis {
+    Axis::X => {
+      if x > *fold_value {
+        (2 * *fold_value - x, y)
+      } else {
+        (x, y)
+      }
+    }
+    Axis::Y => {
+      if y > *fold_value {
+        (x, 2 * *fold_value - y)
+      } else {
+        (x, y)
+      }
+    }
+  }
+}
+