From f4cb00ba69836fb7dee4205617d1a43ac22e241e Mon Sep 17 00:00:00 2001 From: Bauke Date: Tue, 14 Dec 2021 20:23:48 +0100 Subject: [PATCH] Solve day 13! --- source/day_13/canvas.rs | 69 ++++++++++++++++++++++++++++++++ source/day_13/mod.rs | 88 +++++++++++++++++++++++++++++++++++++++++ source/main.rs | 2 + 3 files changed, 159 insertions(+) create mode 100644 source/day_13/canvas.rs create mode 100644 source/day_13/mod.rs diff --git a/source/day_13/canvas.rs b/source/day_13/canvas.rs new file mode 100644 index 0000000..831e319 --- /dev/null +++ b/source/day_13/canvas.rs @@ -0,0 +1,69 @@ +use std::{collections::HashSet, fmt::Display}; + +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct Point(pub isize, pub isize); + +#[derive(Debug)] +pub enum Fold { + Horizontal(isize), + Vertical(isize), +} + +#[derive(Debug)] +pub struct Canvas { + pub width: isize, + pub height: isize, + pub points: HashSet, +} + +impl Canvas { + pub fn fold(self, fold: &Fold) -> Self { + let (width, height) = match fold { + Fold::Horizontal(amount) => (self.width, *amount), + Fold::Vertical(amount) => (*amount, self.height), + }; + + let mut points = HashSet::new(); + for Point(x, y) in self.points { + if y > height { + points.insert(Point(x, height - (y - height))); + continue; + } + + if x > width { + points.insert(Point(width - (x - width), y)); + continue; + } + + points.insert(Point(x, y)); + } + + Self { + width, + height, + points, + } + } +} + +impl Display for Canvas { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for y in 0..self.height { + for x in 0..self.width { + if x % (self.width / 8) == 0 { + write!(f, " ")?; + } + + if self.points.contains(&Point(x, y)) { + write!(f, "█")?; + } else { + write!(f, " ")?; + } + } + + writeln!(f)?; + } + + Ok(()) + } +} diff --git a/source/day_13/mod.rs b/source/day_13/mod.rs new file mode 100644 index 0000000..56b92a7 --- /dev/null +++ b/source/day_13/mod.rs @@ -0,0 +1,88 @@ +use std::collections::HashSet; + +use color_eyre::{eyre::eyre, Result}; + +mod canvas; + +use canvas::{Canvas, Fold, Point}; +use itertools::Itertools; + +pub fn solve() -> Result<()> { + let input_data = include_str!("../../data/day_13.txt").trim(); + println!("Day 13 Part 1: {}", part_1(input_data)?); + println!("Day 13 Part 2:\n{}", part_2(input_data)?); + Ok(()) +} + +fn parse(input: &str) -> Result<(Canvas, Vec)> { + let mut canvas = Canvas { + width: 0, + height: 0, + points: HashSet::new(), + }; + + let mut in_folds_section = false; + let mut folds = vec![]; + + for line in input.lines() { + if line == "" { + in_folds_section = true; + continue; + } + + if in_folds_section { + let mut split = line.split("="); + let is_x_axis = split + .next() + .map(|s| s.ends_with("x")) + .ok_or_else(|| eyre!("Invalid line: {}", line))?; + + let amount = split + .next() + .map(str::parse) + .ok_or_else(|| eyre!("Expected number: {}", line))??; + + if is_x_axis { + folds.push(Fold::Vertical(amount)); + } else { + folds.push(Fold::Horizontal(amount)); + } + } else { + let (x, y) = line + .split(",") + .tuples() + .next() + .ok_or_else(|| eyre!("Invalid line: {}", line))?; + + let x = x.parse()?; + let y = y.parse()?; + if canvas.width < x { + canvas.width = x; + } + + if canvas.height < y { + canvas.height = y; + } + + canvas.points.insert(Point(x, y)); + } + } + + Ok((canvas, folds)) +} + +fn part_1(input: &str) -> Result { + let (mut canvas, folds) = parse(input)?; + canvas = canvas.fold(&folds[0]); + Ok(canvas.points.into_iter().count()) +} + +fn part_2(input: &str) -> Result { + let (mut canvas, folds) = parse(input)?; + + for fold in folds { + canvas = canvas.fold(&fold); + } + + Ok(format!("{}", canvas)) +} diff --git a/source/main.rs b/source/main.rs index 3787895..1860461 100644 --- a/source/main.rs +++ b/source/main.rs @@ -12,6 +12,7 @@ mod day_07; mod day_08; mod day_09; mod day_10; +mod day_13; mod day_14; fn main() -> Result<()> { @@ -30,6 +31,7 @@ fn main() -> Result<()> { day_08::solve, day_09::solve, day_10::solve, + day_13::solve, day_14::solve, ];