From b0821bc945933e7f12750cf094688a57c081c86f Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sun, 10 Apr 2022 16:08:48 +0200 Subject: [PATCH] 2021 day13/rust: add solution --- 2021/day13/day13_rs/Cargo.toml | 9 ++++ 2021/day13/day13_rs/src/main.rs | 83 +++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 2021/day13/day13_rs/Cargo.toml create mode 100644 2021/day13/day13_rs/src/main.rs diff --git a/2021/day13/day13_rs/Cargo.toml b/2021/day13/day13_rs/Cargo.toml new file mode 100644 index 0000000..79b502f --- /dev/null +++ b/2021/day13/day13_rs/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day13_rs" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +nom = "7.1.0" diff --git a/2021/day13/day13_rs/src/main.rs b/2021/day13/day13_rs/src/main.rs new file mode 100644 index 0000000..cc9e4e8 --- /dev/null +++ b/2021/day13/day13_rs/src/main.rs @@ -0,0 +1,83 @@ +#![warn(clippy::pedantic)] +use std::collections::HashSet; +use std::io::{stdin, Read}; + +use nom::bytes::complete::tag; +use nom::character::complete::{anychar, newline, u32}; +use nom::combinator::{map, map_opt}; +use nom::multi::many1; +use nom::sequence::{preceded, separated_pair, terminated}; + +type Input<'a> = &'a str; +type IResult<'a, T> = nom::IResult, T>; + +type Point = (usize, usize); + +fn point(i: Input) -> IResult { + separated_pair(map(u32, |i| i as usize), tag(","), map(u32, |i| i as usize))(i) +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +enum Fold { + X(usize), + Y(usize), +} + +fn fold(i: Input) -> IResult { + map_opt( + preceded( + tag("fold along "), + separated_pair(anychar, tag("="), map(u32, |i| i as usize)), + ), + |(dimension, position)| match dimension { + 'x' => Some(Fold::X(position)), + 'y' => Some(Fold::Y(position)), + _ => None, + }, + )(i) +} + +fn input(i: Input) -> IResult<(Vec, Vec)> { + separated_pair( + many1(terminated(point, newline)), + newline, + many1(terminated(fold, newline)), + )(i) +} + +fn do_fold(points: impl Iterator, fold: Fold) -> HashSet { + let transform = |x, n| if x < n { x } else { n - (x - n) }; + points + .map(|(x, y)| match fold { + Fold::X(n) => (transform(x, n), y), + Fold::Y(n) => (x, transform(y, n)), + }) + .collect() +} + +fn main() { + let mut data = String::new(); + stdin().lock().read_to_string(&mut data).unwrap(); + let (points, folds) = input(&data).unwrap().1; + + let mut points: HashSet<_> = points.into_iter().collect(); + let mut folds = folds.into_iter(); + + points = do_fold(points.into_iter(), folds.next().unwrap()); + println!("{}", points.len()); + + for fold in folds { + points = do_fold(points.into_iter(), fold); + } + + for row in 0..=points.iter().map(|&(_, y)| y).max().unwrap() { + for col in 0..=points.iter().map(|&(x, _)| x).max().unwrap() { + if points.contains(&(col, row)) { + print!("#"); + } else { + print!("."); + } + } + println!(); + } +}