89 lines
1.8 KiB
Rust
89 lines
1.8 KiB
Rust
use std::collections::HashSet;
|
|
|
|
use color_eyre::{eyre::eyre, Result};
|
|
|
|
mod canvas;
|
|
|
|
use canvas::{Canvas, Fold, Point};
|
|
use itertools::Itertools;
|
|
|
|
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<Fold>)> {
|
|
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<usize> {
|
|
let (mut canvas, folds) = parse(input)?;
|
|
canvas = canvas.fold(&folds[0]);
|
|
Ok(canvas.points.into_iter().count())
|
|
}
|
|
|
|
fn part_2(input: &str) -> Result<String> {
|
|
let (mut canvas, folds) = parse(input)?;
|
|
|
|
for fold in folds {
|
|
canvas = canvas.fold(&fold);
|
|
}
|
|
|
|
Ok(format!("{}", canvas))
|
|
}
|