use std::collections::HashSet; use std::error::Error; use std::fs::File; use std::io::{self, BufRead}; use std::vec::Vec; enum Fold { X(i32), Y(i32), } fn fold_x(coord: i32, points: &HashSet<(i32, i32)>) -> HashSet<(i32, i32)> { let left_points: HashSet<(i32, i32)> = points .iter() .filter(|(x, _)| x <= &coord) .cloned() .collect(); let right_points: HashSet<(i32, i32)> = points .difference(&left_points) .map(|(x, y)| (coord - (x - coord), y.clone())) .collect(); left_points.union(&right_points).cloned().collect() } fn fold_y(coord: i32, points: &HashSet<(i32, i32)>) -> HashSet<(i32, i32)> { let below_points: HashSet<(i32, i32)> = points .iter() .filter(|(_, y)| y <= &coord) .cloned() .collect(); let above_points: HashSet<(i32, i32)> = points .difference(&below_points) .map(|(x, y)| (x.clone(), coord - (y - coord))) .collect(); below_points.union(&above_points).cloned().collect() } fn print_points(points: &HashSet<(i32, i32)>) { let mut max_x = 0; let mut max_y = 0; for (x, y) in points.iter() { if x > &max_x { max_x = *x; } if y > &max_y { max_y = *y; } } for y in 0..max_y + 1 { for x in 0..max_x + 1 { if points.contains(&(x, y)) { print!("#") } else { print!(".") } } println!(""); } } fn main() -> Result<(), Box> { let file = File::open("inputs/day13.txt")?; let mut lines = io::BufReader::new(file).lines(); let mut points: HashSet<(i32, i32)> = HashSet::new(); while let Some(Ok(line)) = lines.next() { if line == "" { break; } let mut coords = line.split(',').map(|c| -> i32 { c.parse().unwrap() }); points.insert((coords.next().unwrap(), coords.next().unwrap())); } let mut folds: Vec = Vec::new(); while let Some(Ok(line)) = lines.next() { if line == "" { break; } let mut parts = line.split("="); let inst = parts.next().unwrap(); let coord: i32 = parts.next().unwrap().parse().unwrap(); match inst { "fold along x" => folds.push(Fold::X(coord)), "fold along y" => folds.push(Fold::Y(coord)), _ => panic!("Unkonwn instruction: {}", inst), } } let mut answer1: Option = None; let mut folded_points = points.clone(); for fold in folds.iter() { match fold { Fold::X(x) => folded_points = fold_x(*x, &folded_points), Fold::Y(y) => folded_points = fold_y(*y, &folded_points), } if answer1.is_none() { answer1 = Some(folded_points.len()); } } println!("Answer1: {}", answer1.unwrap()); println!(""); println!("Answer2:"); print_points(&folded_points); Ok(()) }