From 549ee502b1f679f21b9d03b821270ee453190db8 Mon Sep 17 00:00:00 2001 From: kageru Date: Mon, 20 Dec 2021 15:31:46 +0100 Subject: [PATCH] wip day 20 test passes, but real input is wrong --- 2021/inputs/day20 | 102 ++++++++++++++++++++++++++++++++++ 2021/src/bin/day20.rs | 114 ++++++++++++++++++++++++++++++++++++++ 2021/src/grid.rs | 30 ++++++---- 2021/src/grid/position.rs | 19 +------ 4 files changed, 237 insertions(+), 28 deletions(-) create mode 100644 2021/inputs/day20 create mode 100644 2021/src/bin/day20.rs diff --git a/2021/inputs/day20 b/2021/inputs/day20 new file mode 100644 index 0000000..8949da3 --- /dev/null +++ b/2021/inputs/day20 @@ -0,0 +1,102 @@ +#.#..#.#...##.###.##.#.###....#..##..#.#####.#.##.#.##..##..#.#.######..##..####.#....#.#....##....#####..#######..###..#.##..#....#....#....#..#..#..##...####..###.##..##..#.#.#.#.#.#.#..##.###.##.#.##.#.##.#####..###.#.#...##..##...###...###..##...##.######....####.###...####.##.....###.##.#.##.#.....##.##..###.....#..##....#.##.#...##.###.###.#..####....#.###...#....#..###...##..#####..#.######..#.#....####.####.#.#....#.###..##...#.###.####....#.##.#....##...##.#..#....#.##...#....#.####..#.#..####.#... + +####.#.#####..#.#####..###.###...##...##.#.##.###..#...#......##.##..##.####.........#..##...#.####. +#.#.###...###.####....##..##......##.#.####...#########.#.###.#.#.#..###..##...###.###.#.######.#.#. +##...#.#..##.#.##...#..##.####.###.###..###...#####.##.#..##.#.#####.###...#.###.....#######..##...# +####..#.###..####..##...#..######.##.#...#.#..#...#.##..####...##...#.#.#.##.##......##.##.#.##..... +.#########.###.###..#......##.###.####.#..###.#.##.####.#..###....##.##.##.#..##..#..##..#.##.#.#... +..#.#.#...#.###...##..#.#....#.###..#.##...#.#....#.##.#.##.##..###.##.####..#.###.#.####..##....### +.##....#.#.##.....####..#..##...#..............#...###.####....#..#....##.####..###....##...#.###.## +.#.########..###.#..###.#..###.#.##.#.#.#.###...##..##.#.#..#..##.#......###.###..#.##.####.....#... +...###.#...#.##..#...##..###...###...#....#..#.#######...#..##..###.#.#......#.#..###..#.#.###.#..## +..#####...##.##.....#.#####....#..#.#......#.#.#....####.##..#.##.##..##.#########.##.###...###...## +#...#...#####....##.#.#.###......##.#####.#.###.#.#.#.####...##.#..#.#.#..#.#..####..##...#.#....#.. +.#..#.##.#.#.##.#..#.######.#.#....#.##.#..#.#.##...####..##.##..####.####.#...#...#####.#....####.. +.....#.##..#.#.###.##....##....##.##.#...###.#.#..#.##.###.#...#...#.#####..#.##.....#...#.#.#.#.... +....##.##...##..##.########...###...###..###..#..#...####..#..#..####.#..#.#.....###.#..#.#...#..#.. +...#.#.#.###...#...#####.#....##..####..##.####.#..###..#.##.###...#...#..#.##...##.#...#.....###... +##....#..#.#...#.......#.##.######....#..##.##..#...###.#..###..#.#..##.#.........##..###.#......#.# +###...#########.#....###...#.#...#.#..#..##.##.#..#.#......##.#.##.#....#########...#.#.##..######## +.###...#######.#......####.#.##.###.##.#..##.###.##..########.#..##.##..#..#..#...#.#..###..##...### +..#...##.....#.#..###.#..#.##.#..#.#.#.##.#####....####.#.#..#...##.##.##.#..####.#..#.#####......#. +#...##..##########.......#.....##.####..#####..##...#...##..###.#.#.#.#.#####.####.##.##.#.#.....### +.#.###.#..#..###.#..#.#.#....#.#####.##....#.#.#..##.#.#.#.###.#..#..##..#..###....#...##.#..#.#.#.# +...###.#..#....##.#...#...#..#....###...#.....#..####.##..#.###...#....###..##.#.##...#..##..#.##.#. +#.#.###.#..#....##.#..#####..###...##.##...#...###.#.##.#.#.#...#.#.#....####..#.##..##...#.#.##...# +.#..#..#..##########.#.###.#..##..##.#.##.#..#.##..#..#.#.##....##..##....##.######..#....#.#..##### +...#.##.#.###.#..#####.#........#.#.####.##..##..#.#..##...#..#..#..#.#.#.#..#..#.###..#..#.####.### +.###...###.#..#..#....##.#.##.#.....#..#.#.#...##.##.#...####..##..#.#..#...#....###.#..#####.#####. +...#.#.##.#......#.#....#####..#.#..##..#.#.#..###.##...#..#..##...#...#######.###.#####.###...#.... +.##....#...###..####....#.#..##.#.#.##..###########...#.###..#.##.##.##.#....##.##..####......###... +#.##......#.##.###.##...##..#.##.#.##.##..#..#.#####....##.##.###.#########.#..###.....#....##..##.# +#.####.#.#...#.#.#.##..##.###..###.#..#..#####...####.####....#.##...####..#######.#....#######.#.#. +##...#..#...##...#.#...#.##.#......#.#.#.....#.#.#....#.#.#...#.#.#######.##.#.#..##..#....#.#..#..# +#..##..#.#..#.#..#.#.#.#.#....#.#.##.##.#.##.....##...##...##.#####.#.###.#..#..####.#.#..#######.#. +.#.##..#.##..#....##.#.#..#..##..##...#...######.###....#..#...##..#.#..........#.######.........#.. +###.#.#..#.#..#.#.#.##..######.#.......###.###.#..#....#.##.#####.#.###.##.####.#.##..##.##.####.#.. +##.#...#.....#...##.##.##....########......#.#.#...#.#..#.#....###...##.##...........####.##.##..#.# +####.###.#.#...#.##....#.##..###..#.#.#####..####.#.#..#..#....#...#..#...##...#..#.###..###..#.#.## +#.#..#..#.###....##.#..##.#..#...##..##..#.#.#.#..#...##.######..#.#..####.#.###..####..##...#.#...# +.###...#...#####...#.#...#.##..#...###.##.###...#..#.#.#.#...#.##.##.##.##.##...#...#.###.#.#......# +#.......#.#....####.....#..#.#.#..##.#####..##..#..###.#..#..##...####....##.#.#..###...#.##.#.###.. +#.#..#.#.##.#.#####.#######.#####.#..###..#.#.......#.##...#..##..##....#.#..######.....##.##..##.## +#####.#....######.....##.#...#..##....#...###.##..#..##..###.###..###.####..#...#######....######... +#####.........#....#....#..#####.###.#..#.#....##.##..###..#..#.#...#.##...#.#..##..#.#.###.####.#.# +...###.#####.#.##..###.....#.#.......##...#....#.#.##.#......#.#...#.#..#...#.####.######.##...##.## +#...#..#..#..#...##.#.....#.#.##..####..##.#..#.#.#####.#.##.###.#....###...######........#..#..##.. +..##.......##.##.#....###.#...#...#.##.###..###.#..####.#.######.#..#######.......#.##..#.####...#.# +......##.##..#####.##....#..#..##.#...#...####..##...##.##.#....#....#.#.###.....##..##.#...##....#. +####...#......#.#........##.#..#...#.#.###..#....##.###.#..#.#.##.##......#.#...#.##...##.###..#.### +.##....##..##.########.##..##..#.#.....#..#...#.#.#.#..#.##..#.##.#..#.#....####......#..#...#.#.#.. +.##.#...#.##.##.#.#..###..#.#...##.#.#.#.##..#..######..##.#.##....###.#....##..#.###.##.##..#...#.# +..#.#.#...#...###..##....#.##..#..#...#....#.#...#####...##.####.#.#...#..#.##.###...#...#..#.##.... +...#.####.###.#...#####..####.####..#.##...########...#.#...#.##.#.#..##.#..#..##.###.#####..##.##.# +##.#.#..##.###.##.#......###.#..#.#..#.#...#.#.#...#.##.###.#####.##..##...##.#..#..#.....#.###....# +......##.#..###....#.#####.###.###.###...#.....####.###.........#....###.####.#.......#..#........#. +...####.##....#.#.#.#.##..#..#.#..##....#...##..#...#.#..#.####..#.##.##.##......###..#...####..#.## +##.#.#####.....#...####.##.#.#.####.#......#.######...######.##.######....##..######..##.#...##.#..# +..#.##.......#.#####.#......###.###.##..####.#.###....#.###.#..#..#########..#..#..##.##.#....#....# +....####...#.#.#...####.#.#..###...#...#..##.##..####.#.#..##.#.#.#.###...........##..##..####.####. +#.#..###..######..##.##..#...#.#####......#.....######.##..#.#####...##..####.###.#..######...#.###. +..#####.#..#...#.####.###.#..##....####.#.#.#.#.##.####.#.##.###.###...#..#...#.##..##...#.....#.... +..#.##.#..##....####.#.....##.##...##.#.#.####.##.#..####...###..#.#.######.#.###..#..#...#....##.## +#...##.#...#.###...#.##...#.#..###.#####.#....#########....##.#..###..##......#.#.........#.#...##.# +##..##.#.#...#..#..#####..#.#....#...###.##..#.####..#......##..##..##..#....#..#####.#.#.####.##..# +#.###...###..#.......#.#.##.##..###.####...##.##.#..#.#..#..#.###...#..######......##...##.##.#..#.# +.####.#...##.#..#...#.###..##.#..##.....###..###..##.####...#....#######.#.############.##.....##.## +#..####.#..#........##.#.#.#####.#.#.#.#.##.#..#...#..##...#...#.#..##.###.#.#######.#.#####..#.###. +#######...#####.#.##..####.#......##.#..#.###.####.#......####.#.##.#..##...#.....#.##.####.##.....# +#.....#......##...#.#.##.####.######...#.....#..##..##.####....##..##..#.#.##..###.##...#.##..#..### +....##.#..#.#..##.####.#.##..##.#.##.##.#..##########.#..##.....##....#.##.#...#.#..#..#..#.#.#.###. +#......###......###.#.#.#..##....##..##..##.#..#.#.####.####...##.#...##.####..#.....#...#.#.#####.. +###..###.#...#..###.#......####.##.#.#.###...#..........##......####.###.###.#..#.....#####..####.## +..#.####..#...##.###...####.##.......#.##.##.#.#.#.##....#..###.....#....###.#..#...######.#...#..#. +#..#..#.#..#...#.#.###.####.##........#.##.####..#..############.#.###...###.#######.#.#....#...###. +#.######.###.##.#..#####.#.#....##.#.##..#######..##...##...#...##..##...#.##.##.#####...##.#...##.. +##.###.###..##..##.#.#.##..#...#.#...##.#.........#.#.#.......###...#.##..#.##.#.##.####...##...###. +..#.##..####.##...##....###.#...#..#..##.##..###..###.###...#.#.#.####..#.#.##...#.#..####...#..##.# +#.#.#..#....#.#.#.#......#..#..#...#.#...#...#..#..#.##..#..#....#.##..#..#...##.######..#..##.##### +.#..##..#.#...#..#..##....##.....#....##.#..######...##.##.......#.#.....#####.####.#.##.#.#.##.###. +##.#..##.#...#..#.####...###..##.#####....#..#...#.##...#.#..###...####.#.##....#..#.#.##.#..####... +#.#######...##.####..#...#...##.#.###..#..###.#.#..#.###.#.##.#.###....#.##..###..#.#.########...... +###.##.###.#...##....#.#..##.###.#..#.#.##.#.##....#.#####...###..###..#..##..#..#.#..#####.###..#.. +.###.###.##..##..#######.##########.#.###.#.#.#....#..#.###...##.##.....#..#....###.....#....##...## +##...###.##.##....#.#....#####..#.######.##.#########..#.#...#.##....#.####.#.###.##.####.#.#.#####. +###.###.....##.###.#..##.#...#......#.###.#..##.#...###..##.#.#.#...###.#.#...##..##....#####....##. +#.#..#..###.##.##.##....#..###.#.###..#######.#...####..#####..#.......#..#.#.##.#..##..#.####..##.# +..##....##...###.###...#.###.....####.#..###.#.........#....####.#..#.#.##...#...###...#.##.....###. +.#..#.##.#.#.#.#.#..###.#..#.#.#######.####.###..#.#.##.......##.#...#...##..##.##.#.#..##.###.###.. +#.#..#...#...###.#.#....#..#..###.#####.#.#.#..##.#.#........###.#.#...#.....#..###..##.##..###..#.. +....#.#..#..##..#....###....#....###..##...#.#....#.###.####..#.#.##.####.#..#..##.....#.##.#...#.#. +...#..#.#.#..#.###...###...####..#....###.##.#..###.##.#.#.#.##...#...#.#...##....#.#.##.#.##..#.#.. +##.#..###...#...##..#....###.#.##....##.#.##.#.##....####..#...#.#####.....#.##.#..#.#.###.#....#..# +#.#.##..#..##.##..##.##.#####.####..#..#..#....###.##.#..#####.##.#####..######.#...#...#..#.#..###. +..#.#......#..##.#...#.#..###..####.##.##..#..#####.##....#.##.....###.###........##.......##.#.#### +##..##.#.#.#..##..#.#.#..##.#.######...##..##...##..#####.#...#.#.....###.#...##....#...#.#.#...###. +#......#.###.##.#####..##.#..#.#...######....#..#....#...#####.#.#.#.#.#...####..#...#.....#..#.#.## +..##.##..####...##.#...##...#####...#...#.##.###..#....####.#..#..#.####.##..##.#..####..#.#..####.. +#####.#...#.##..##.#..####.#.#..#.#....#.####.#.####..#..####...#.#..##.#.#....#####..#..####..#...# +..#.......##.#..##.#..#..#.######.#...#.....###.###.####..#.#....#..#...#.#..#..##...#.##.#######.## +#.##..##..#.#.#####.........###..##.#.#...###.#.###...###.#...###..##..#.###..#.#.#....####...##.... +##....#.##.##.#..###...#.#.##..#.#......#...#.#.#.#.#..###.#.....#.##.##..#.###..##..###.##....##### +...#.#..#...#..##...##....##....#.#..###..#....#..#.#.###.....##....#..#....##.###....#.#..#.#.#.#.. diff --git a/2021/src/bin/day20.rs b/2021/src/bin/day20.rs new file mode 100644 index 0000000..f2f3e6b --- /dev/null +++ b/2021/src/bin/day20.rs @@ -0,0 +1,114 @@ +#![feature(derive_default_enum)] +#![feature(test)] +extern crate test; +use std::fmt; + +use aoc2021::{ + common::*, + grid::{draw_ascii, get_boundaries, Boundaries, Grid, HashGrid, Position2D}, +}; +use itertools::Itertools; + +#[derive(Debug, PartialEq, Default, Clone, Copy)] +enum Pixel { + Bright, + #[default] + Dark, +} + +#[rustfmt::skip] +impl fmt::Display for Pixel { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", match self { Pixel::Bright => '#', Pixel::Dark => '.' }) + } +} + +impl From for Pixel { + fn from(b: u8) -> Self { + match b { + b'#' => Pixel::Bright, + b'.' => Pixel::Dark, + _ => unreachable!(), + } + } +} + +const DAY: usize = 20; +type Parsed = ([Pixel; 512], HashGrid); + +fn parse_input(raw: &str) -> Parsed { + let (enhance, image) = raw.split_once("\n\n").unwrap(); + // type inference on these methods is absolute magic + (enhance.bytes().map_into().collect_vec().try_into().unwrap(), HashGrid::from_bytes_2d(image, Pixel::from)) +} + +fn neighbors_plus_self(p: Position2D) -> Vec { + (-1..=1) + .rev() // my grid has (0,0) at top left which doesn’t seem to match the task + .flat_map(|x| (-1..=1).rev().map(move |y| Position2D::from([y, x]))) + .map(|offset| p + offset) + .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 { + 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)])) + .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); + idx +} + +fn part2(parsed: &Parsed) -> usize { + unimplemented!() +} + +fn main() { + let input = parse_input(&read_file(DAY)); + println!("Part 1: {}", part1(&input)); + println!("Part 2: {}", part2(&input)); +} + +#[cfg(test)] +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); + assert_eq!(idx, 34); + } + + test!(part1() == 35); + test!(part2() == 0); + // bench!(part1() == 5573); // too high + bench!(part2() == 0); + bench_input!(|(_, g): &Parsed| g.len() => 10_000); +} diff --git a/2021/src/grid.rs b/2021/src/grid.rs index bc594ee..c4f1543 100644 --- a/2021/src/grid.rs +++ b/2021/src/grid.rs @@ -2,7 +2,7 @@ pub mod cell; pub mod direction; pub mod position; pub use direction::*; -use itertools::join; +use itertools::{join, Itertools, MinMaxResult}; pub use position::*; use std::{collections::HashMap, fmt::Display, hash::BuildHasher}; @@ -34,7 +34,7 @@ impl Grid for HashGrid { } } -impl HashGrid { +impl HashGrid { pub fn from_bytes_2d T + Copy>(raw: &str, mut f: F) -> HashGrid { raw.lines() .enumerate() @@ -75,18 +75,24 @@ impl VecGrid { } } -struct Boundaries { - x_min: i64, - x_max: i64, - y_min: i64, - y_max: i64, +pub struct Boundaries { + pub x_min: i64, + pub x_max: i64, + pub y_min: i64, + pub y_max: i64, } -fn get_boundaries(input: &[&PositionND<2>]) -> Boundaries { - let x_min = input.iter().min_by_key(|k| k.points[0]).map(|p| p.points[0]).unwrap_or(0); - let x_max = input.iter().max_by_key(|k| k.points[0]).map(|p| p.points[0]).unwrap_or(0); - let y_min = input.iter().min_by_key(|k| k.points[1]).map(|p| p.points[1]).unwrap_or(0); - let y_max = input.iter().max_by_key(|k| k.points[1]).map(|p| p.points[1]).unwrap_or(0); +pub fn get_boundaries(input: &[&PositionND<2>]) -> Boundaries { + let (x_min, x_max) = match input.iter().map(|p| p.points[0]).minmax() { + MinMaxResult::NoElements => (0, 0), + MinMaxResult::MinMax(min, max) => (min, max), + MinMaxResult::OneElement(x) => (x, x), + }; + let (y_min, y_max) = match input.iter().map(|p| p.points[1]).minmax() { + MinMaxResult::NoElements => (0, 0), + MinMaxResult::MinMax(min, max) => (min, max), + MinMaxResult::OneElement(x) => (x, x), + }; Boundaries { x_min, x_max, y_min, y_max } } diff --git a/2021/src/grid/position.rs b/2021/src/grid/position.rs index 7d6b34e..449ae6a 100644 --- a/2021/src/grid/position.rs +++ b/2021/src/grid/position.rs @@ -6,38 +6,25 @@ use std::{ ops::{Add, Mul, Sub}, }; -pub trait Position -where Self: Sized + Hash + PartialEq + Eq + Clone + Copy -{ - fn neighbors(&self) -> Vec; -} - #[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)] pub struct PositionND { pub points: [i64; DIMS], } +pub type Position2D = PositionND<2>; + impl From<[I; D]> for PositionND where I: TryInto + Copy { fn from(s: [I; D]) -> Self { let mut points = [0; D]; for i in 0..D { - points[i] = unwrap_number_result(s[i]); + points[i] = s[i].try_into().unwrap_or_else(|_| panic!("number did not fit in target type")) } Self { points } } } -// because calling .unwrap() on a TryInto result isn’t possible without trait bounds on the -// associated Error type. -fn unwrap_number_result>(i: I) -> i64 { - match i.try_into() { - Ok(i) => i, - _ => panic!("Bad coordinate"), - } -} - pub const fn num_neighbors(d: usize) -> usize { 3usize.pow(d as u32) - 1 }