116 lines
3.0 KiB
Rust
116 lines
3.0 KiB
Rust
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(())
|
|
}
|