use std::env; use std::io::{self}; use std::collections::HashSet; extern crate regex; use regex::Regex; use point2d::point2d::Point2D; enum Fold { AlongX(i64), AlongY(i64) } impl From<&str> for Fold { fn from(s: &str) -> Self { let re = Regex::new(r"fold along ([xy])=(\d+)").unwrap(); let matches = re.captures(s).unwrap(); match &matches[1] { "x" => Self::AlongX(matches[2].parse().unwrap()), "y" => Self::AlongY(matches[2].parse().unwrap()), other => panic!("Unknown fold type: {}", other), } } } fn map_extents(map: &HashSet) -> (i64,i64,i64,i64) { let xmin = &map.iter().map(|&pt| pt.x).min().unwrap(); let ymin = &map.iter().map(|&pt| pt.y).min().unwrap(); let xmax = &map.iter().map(|&pt| pt.x).max().unwrap(); let ymax = &map.iter().map(|&pt| pt.y).max().unwrap(); (*xmin,*ymin,*xmax,*ymax) } fn solve(input: &str) -> io::Result<()> { // Input let input_str = std::fs::read_to_string(input).unwrap(); let input_str = input_str.trim(); let input: Vec<_> = input_str.split("\n\n").collect(); let initial_points: Vec<_> = input[0].split("\n").collect(); let folds: Vec<_> = input[1].split("\n").map(Fold::from).collect(); // Build initial image let mut image: HashSet = HashSet::new(); let re = Regex::new(r"(\d+),(\d+)").unwrap(); for point in initial_points { let matches = re.captures(&point).unwrap(); let (x,y) = (matches[1].parse().unwrap(),matches[2].parse().unwrap()); image.insert(Point2D{x: x, y: y}); } // Process folds let (_,_,mut xmax,mut ymax) = map_extents(&image); for (i,fold) in folds.iter().enumerate() { // Part 1 if i == 1 { let part1 = image.iter().filter(|&pt| pt.x <= xmax && pt.y <= ymax).count(); println!("Part 1: {}", part1); // 743 } match &fold { Fold::AlongX(cut) => { for y in 0..=ymax { for x in *cut..=xmax { let pt = Point2D { x: x, y: y }; let newpt = Point2D { x: 2*cut-x, y }; if image.contains(&pt) { image.insert(newpt); } } } xmax = *cut; }, Fold::AlongY(cut) => { for y in *cut..=ymax { for x in 0..=xmax { let pt = Point2D { x: x, y: y }; let newpt = Point2D { x: x, y: 2*cut-y }; if image.contains(&pt) { image.insert(newpt); } } } ymax = *cut; }, } } println!("Part 2:"); // RCPLAKHL for y in 0..=ymax { for x in 0..=xmax { match image.contains(&Point2D { x: x, y: y }) { true => { print!("█"); }, _ => { print!(" "); }, } } println!(); } Ok(()) } fn main() { let args: Vec = env::args().collect(); let filename = &args[1]; solve(&filename).unwrap(); }