Add day 20

This commit is contained in:
kageru 2021-12-20 16:05:38 +01:00
parent 549ee502b1
commit 165da4c28c
2 changed files with 31 additions and 35 deletions

View File

@ -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<Position2D> {
.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<Pixel, 2>, lookup: &[Pixel; 512]) -> HashGrid<Pixel, 2> {
fn step(grid: HashGrid<Pixel, 2>, lookup: &[Pixel; 512], iteration: usize) -> HashGrid<Pixel, 2> {
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<Pixel, 2>) -> 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<Pixel, 2>, 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<Pixel, 2>, 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);
}

View File

@ -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([<TEST_INPUT $input>]);
assert_eq!($part $(::<$gen>)? (&input$(, $param)*), $expected);
}