mod canvas; use canvas::{Canvas, Fold, Point}; use crate::prelude::*; pub fn solution() -> Solution { Solution::new(Day::new(13, 2021), part_1, part_2).with_expected( "712", " ███ █ █ █ ████ ██ ███ ██ ████ █ █ █ █ █ █ █ █ █ █ █ ███ █ ████ ███ █ █ █ █ ███ █ █ █ █ █ █ █ ███ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ███ ████ █ █ █ ██ █ ██ █ ", ) } 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.is_empty() { 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.len().to_string()) } fn part_2(input: &str) -> Result { let (mut canvas, folds) = parse(input)?; for fold in folds { canvas = canvas.fold(&fold); } Ok(format!("{}", canvas)) }