From 50db6dafd060762b0fe31975da4189675ffae7d9 Mon Sep 17 00:00:00 2001 From: Joseph Montanaro Date: Wed, 29 Dec 2021 07:05:02 -0800 Subject: [PATCH] day 13 --- 2021/src/day13.rs | 131 ++++++++++++++++++++++++++++++++++++++++++++++ 2021/src/lib.rs | 20 +++++++ 2021/src/main.rs | 6 +-- 3 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 2021/src/day13.rs diff --git a/2021/src/day13.rs b/2021/src/day13.rs new file mode 100644 index 0000000..f2a44b7 --- /dev/null +++ b/2021/src/day13.rs @@ -0,0 +1,131 @@ +use color_eyre::eyre; +use eyre::eyre; + +use crate::lib::{Vec2, IterExt}; + + +enum Direction { + Horizontal, + Vertical, +} + +struct Line { + value: usize, + direction: Direction, +} + + +fn load(data: &str) -> eyre::Result<(Vec2, Vec)> { + // populate a 1500x1500 grid + let mut grid: Vec2 = Vec2::with_capacity(1500, 1500); + grid.fill_to_cap(false); + + let mut lines = data.lines(); + for line in &mut lines { + if line == "" {break} + + let (col, row) = line.split(',').map(|s| s.parse::()).take_pair()?; + grid.set(row?, col?, true); + } + + // having consumed the coordinates, we can move on to the fold lines + let mut folds = Vec::new(); + for line in lines { + let (axis, intercept) = line + .split(' ') + .nth(2) + .ok_or_else(|| eyre!("Invalid fold line statement: {}", line))? + .split('=') + .take_pair()?; + + let direction = match axis { + "x" => Direction::Vertical, + "y" => Direction::Horizontal, + _ => return Err(eyre!("Invalid axis: {}", axis)), + }; + let value = intercept.parse::()?; + + folds.push(Line {value, direction}); + } + Ok((grid, folds)) +} + + +fn fold(grid: &Vec2, line: &Line) -> Vec2 { + let mut new_rows = grid.row_count(); + let mut new_cols = grid.col_count(); + match line.direction { + Direction::Horizontal => new_rows = line.value, + Direction::Vertical => new_cols = line.value, + } + + let mut new_grid = Vec2::with_capacity(new_rows, new_cols); + new_grid.fill_to_cap(false); + for row in 0..new_rows { + for col in 0..new_cols { + if *grid.get(row, col) { + new_grid.set(row, col, true); + } + + let mut mirror_row = row; + let mut mirror_col = col; + match line.direction { + Direction::Horizontal => mirror_row = 2 * new_rows - row, + Direction::Vertical => mirror_col = 2 * new_cols - col, + } + if mirror_row < grid.row_count() && mirror_col < grid.col_count() + && *grid.get(mirror_row, mirror_col) + { + new_grid.set(row, col, true); + } + } + } + new_grid +} + + +fn show(grid: &Vec2) { + for row in grid.rows() { + let line = row.iter().map(|&v| if v {'#'} else {' '}).collect::(); + println!("[{}]", line); + } +} + + +const SAMPLE: &str = "6,10 +0,14 +9,10 +0,3 +10,4 +4,11 +6,0 +6,12 +4,1 +0,13 +10,12 +3,4 +3,0 +8,4 +1,10 +2,14 +8,10 +9,0 + +fold along y=7 +fold along x=5"; + + +pub fn run(data: &str) -> eyre::Result<(usize, usize)> { + let (grid, folds) = load(data)?; + + let mut folded = fold(&grid, &folds[0]); + let one = folded.values().filter(|v| **v).count(); + + for line in &folds[1..] { + folded = fold(&folded, line); + } + + show(&folded); + + Ok((one, 0)) +} \ No newline at end of file diff --git a/2021/src/lib.rs b/2021/src/lib.rs index 6787be7..eadc466 100644 --- a/2021/src/lib.rs +++ b/2021/src/lib.rs @@ -151,6 +151,10 @@ impl Vec2 { Vec2 {data: Vec::::new(), columns} } + pub fn with_capacity(rows: usize, columns: usize) -> Vec2 { + Vec2 {data: Vec::::with_capacity(rows * columns), columns} + } + pub fn push>(&mut self, row: S) { self.data.extend(row.into_iter()); } @@ -213,6 +217,22 @@ impl Vec2 { } } +#[allow(dead_code)] +impl Vec2 { + pub fn fill(&mut self, value: T) { + for i in 0..self.data.len() { + self.data[i] = value; + } + } + + pub fn fill_to_cap(&mut self, value: T) { + self.fill(value); + for _i in self.data.len()..self.data.capacity() { + self.data.push(value); + } + } +} + impl Index for Vec2 { type Output = [T]; diff --git a/2021/src/main.rs b/2021/src/main.rs index 1696cad..3100cb2 100644 --- a/2021/src/main.rs +++ b/2021/src/main.rs @@ -4,14 +4,14 @@ use color_eyre::eyre; mod lib; use lib::load; -mod day12; +mod day13; fn main() -> eyre::Result<()> { - let data = load("data/12.txt")?; + let data = load("data/13.txt")?; let start = Instant::now(); - let (one, two) = day12::run(&data)?; + let (one, two) = day13::run(&data)?; let (dur, unit) = format_ns(start.elapsed().as_nanos()); let precision = 2.0 - dur.log10().floor();