AoC2021/src/bin/day13.rs

116 lines
3.0 KiB
Rust
Raw Permalink Normal View History

2021-12-13 15:24:44 +01:00
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<dyn Error>> {
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<Fold> = 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<usize> = 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(())
}