Add day 20
This commit is contained in:
parent
549ee502b1
commit
165da4c28c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user