From 165da4c28c106de0c74b7bd40c0acc6e23c5732f Mon Sep 17 00:00:00 2001 From: kageru Date: Mon, 20 Dec 2021 16:05:38 +0100 Subject: [PATCH] Add day 20 --- 2021/src/bin/day20.rs | 64 ++++++++++++++++++++----------------------- 2021/src/teststuff.rs | 2 +- 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/2021/src/bin/day20.rs b/2021/src/bin/day20.rs index f2f3e6b..be4aa91 100644 --- a/2021/src/bin/day20.rs +++ b/2021/src/bin/day20.rs @@ -1,13 +1,12 @@ #![feature(derive_default_enum)] #![feature(test)] extern crate test; -use std::fmt; - use aoc2021::{ common::*, - grid::{draw_ascii, get_boundaries, Boundaries, Grid, HashGrid, Position2D}, + grid::{get_boundaries, Boundaries, Grid, HashGrid, Position2D}, }; use itertools::Itertools; +use std::fmt; #[derive(Debug, PartialEq, Default, Clone, Copy)] enum Pixel { @@ -50,33 +49,39 @@ fn neighbors_plus_self(p: Position2D) -> Vec { .collect() } -fn part1((lookup, grid): &Parsed) -> usize { - let mut grid = grid.to_owned(); - for _ in 0..2 { - // println!("{}\n{}\n\n", grid.len(), draw_ascii(&grid.fields)); - grid = step(grid, lookup); - } - // println!("{}\n{}\n\n", grid.len(), draw_ascii(&grid.fields)); - grid.fields.values().filter(|&&p| p == Pixel::Bright).count() -} - -fn step(grid: HashGrid, lookup: &[Pixel; 512]) -> HashGrid { +fn step(grid: HashGrid, lookup: &[Pixel; 512], iteration: usize) -> HashGrid { let Boundaries { x_min, x_max, y_min, y_max } = get_boundaries(&grid.fields.keys().collect_vec()); - println!("{x_min}, {x_max}, {y_min}, {y_max}"); (x_min - 1..=x_max + 1) .flat_map(|x| (y_min - 1..=y_max + 1).map(move |y| Position2D::from([x, y]))) - .map(|p| (p, lookup[lookup_index(p, &grid)])) + .map(|p| (p, lookup[lookup_index(p, &grid, iteration)])) .collect() } -fn lookup_index(p: Position2D, grid: &HashGrid) -> usize { - let idx = - neighbors_plus_self(p).into_iter().rev().map(|p| grid.get(&p) == Some(&Pixel::Bright)).fold(0, |acc, n| (acc << 1) | n as usize); +const OUTSIDE: [Pixel; 2] = [Pixel::Dark, Pixel::Bright]; + +fn lookup_index(p: Position2D, grid: &HashGrid, iteration: usize) -> usize { + let idx = neighbors_plus_self(p) + .into_iter() + .rev() + .map(|p| grid.get(&p).unwrap_or(&OUTSIDE[iteration & 1]) == &Pixel::Bright) + .fold(0, |acc, n| (acc << 1) | n as usize); idx } -fn part2(parsed: &Parsed) -> usize { - unimplemented!() +fn step_times(grid: &HashGrid, lookup: &[Pixel; 512], iterations: usize) -> usize { + let mut grid = grid.to_owned(); + for i in 0..iterations { + grid = step(grid, lookup, i); + } + grid.fields.values().filter(|&&p| p == Pixel::Bright).count() +} + +fn part1((lookup, grid): &Parsed) -> usize { + step_times(grid, lookup, 2) +} + +fn part2((lookup, grid): &Parsed) -> usize { + step_times(grid, lookup, 50) } fn main() { @@ -90,25 +95,16 @@ mod tests { use super::*; use aoc2021::*; - const TEST_INPUT: &str = "..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..# - -#..#. -#.... -##..# -..#.. -..###"; - #[test] fn lookup_index_test() { let grid = HashGrid::from_bytes_2d("...\n#..\n.#.", Pixel::from); let p = Position2D::from([1, 1]); - let idx = lookup_index(p, &grid); + let idx = lookup_index(p, &grid, 0); assert_eq!(idx, 34); } - test!(part1() == 35); - test!(part2() == 0); - // bench!(part1() == 5573); // too high - bench!(part2() == 0); + // Can’t meaningfully test because test and real behaves completely differently toward infinity + bench!(part1() == 5503); + bench!(part2() == 19156); bench_input!(|(_, g): &Parsed| g.len() => 10_000); } diff --git a/2021/src/teststuff.rs b/2021/src/teststuff.rs index 6e572c9..6232dcb 100644 --- a/2021/src/teststuff.rs +++ b/2021/src/teststuff.rs @@ -37,7 +37,7 @@ macro_rules! test { (with $input: ident: $part: ident $(<$gen: literal>)? ($($param: expr),*) == $expected:expr) => { paste::paste! { #[test] - fn [<$part $($gen)? _$input:lower _test>]() { + fn [<$part $($gen)? $input:lower _test>]() { let input = parse_input([]); assert_eq!($part $(::<$gen>)? (&input$(, $param)*), $expected); }