use std::collections::HashSet; use color_eyre::{eyre::eyre, Result}; use itertools::Itertools; mod canvas; use canvas::{Canvas, Fold, Point}; 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)) }