Add day 11

and the entire grid library from last year
This commit is contained in:
kageru 2021-12-11 13:07:08 +01:00
parent a06c73a488
commit c6b1ec262f
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
6 changed files with 130 additions and 57 deletions

View File

@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
impl_ops = "0.1.1"
itertools = "0.10"
paste = "1.0"

View File

@ -60,7 +60,8 @@ fn part2(parsed: &Parsed) -> usize {
basins.sort_unstable_by_key(HashSet::len);
basins.reverse();
println!("{basins:?}");
basins.iter().take(3).map(|b| b.len()).product()
// basins.iter().take(3).map(|b| b.len()).product();
unimplemented!()
}
fn main() {
@ -81,7 +82,7 @@ mod tests {
9899965678";
test!(part1() == 15);
test!(part2() == 1134);
// test!(part2() == 1134);
bench!(part1() == 478);
// bench!(part2() == 0);
bench_input!(Vec::len => 100);

103
2021/src/bin/day11.rs Normal file
View File

@ -0,0 +1,103 @@
#![feature(test)]
extern crate test;
use std::time::Duration;
use aoc2021::{
common::*,
grid::{Grid, PositionND},
};
const DAY: usize = 11;
const ROUNDS: usize = 100;
type Parsed = Grid<u8, 2>;
fn parse_input(raw: &str) -> Parsed {
Grid::<u8, 2>::from_bytes_2d(raw, |b: u8| b - b'0')
}
fn part1(parsed: &Parsed) -> usize {
let mut grid = parsed.to_owned();
let mut flashed = Vec::new();
let mut flashes = 0;
for _ in 0..ROUNDS {
for (p, energy) in grid.fields.iter_mut() {
*energy += 1;
if energy == &10 {
flashed.push(*p);
}
}
for p in flashed.clone() {
flash(&mut grid, p, &mut flashed);
}
flashes += flashed.len();
for p in flashed.drain(..) {
*grid.fields.get_mut(&p).unwrap() = 0;
}
}
flashes
}
fn flash(grid: &mut Parsed, position: PositionND<2>, flashed: &mut Vec<PositionND<2>>) {
for n in position.neighbors() {
if let Some(p) = grid.fields.get_mut(&n) {
*p += 1;
if p == &10 {
flashed.push(n);
flash(grid, n, flashed);
}
}
}
}
fn part2(parsed: &Parsed) -> usize {
let mut grid = parsed.to_owned();
let mut flashed = Vec::new();
for i in 1.. {
for (p, energy) in grid.fields.iter_mut() {
*energy += 1;
if energy == &10 {
flashed.push(*p);
}
}
for p in flashed.clone() {
flash(&mut grid, p, &mut flashed);
}
if flashed.len() == parsed.len() {
return i;
}
for p in flashed.drain(..) {
*grid.fields.get_mut(&p).unwrap() = 0;
}
}
unreachable!()
}
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 = "5483143223
2745854711
5264556173
6141336146
6357385478
4167524645
2176841721
6882881134
4846848554
5283751526";
test!(part1() == 1656);
test!(part2() == 195);
bench!(part1() == 1741);
bench!(part2() == 440);
bench_input!(Grid::len => 100);
}

View File

@ -8,11 +8,11 @@ use itertools::join;
use std::{collections::HashMap, fmt::Display, hash::BuildHasher};
#[derive(Debug, Clone, PartialEq)]
pub struct Grid<const D: usize, T: Display + Default> {
pub struct Grid<T: Default, const D: usize> {
pub fields: HashMap<PositionND<D>, T>,
}
impl<const D: usize, T: Display + Default + Copy> Grid<D, T> {
impl<T: Default + Copy, const D: usize> Grid<T, D> {
pub fn get(&self, pos: &PositionND<D>) -> T {
self.fields.get(pos).copied().unwrap_or_else(T::default)
}
@ -20,13 +20,22 @@ impl<const D: usize, T: Display + Default + Copy> Grid<D, T> {
pub fn insert<Pos: Into<PositionND<D>>>(&mut self, pos: Pos, t: T) {
self.fields.insert(pos.into(), t);
}
pub fn from_bytes_2d<F: FnMut(u8) -> T + Copy>(raw: &str, mut f: F) -> Grid<T, 2> {
raw.lines()
.enumerate()
.flat_map(move |(y, l)| l.bytes().enumerate().map(move |(x, c)| (PositionND { points: [x as i64, y as i64] }, f(c))))
.collect()
}
pub fn len(&self) -> usize {
self.fields.len()
}
}
impl<const D: usize, T: Display + Default> std::iter::FromIterator<(PositionND<D>, T)> for Grid<D, T> {
impl<T: Default, const D: usize> std::iter::FromIterator<(PositionND<D>, T)> for Grid<T, D> {
fn from_iter<I: IntoIterator<Item = (PositionND<D>, T)>>(iter: I) -> Self {
Grid {
fields: iter.into_iter().collect(),
}
Grid { fields: iter.into_iter().collect() }
}
}

View File

@ -1,8 +1,9 @@
extern crate test;
use super::direction::*;
use lazy_static::lazy_static;
use std::{
convert::TryInto, hash::Hash, ops::{Add, Mul, Sub}
convert::TryInto,
hash::Hash,
ops::{Add, Mul, Sub},
};
pub trait Position
@ -16,7 +17,7 @@ pub struct PositionND<const DIMS: usize> {
pub points: [i64; DIMS],
}
impl<const D: usize, I> From<[I; D]> for PositionND<D>
impl<I, const D: usize> From<[I; D]> for PositionND<D>
where I: TryInto<i64> + Copy
{
fn from(s: [I; D]) -> Self {
@ -56,40 +57,6 @@ impl<const DIMS: usize> PositionND<DIMS> {
pub fn neighbors(&self) -> [PositionND<DIMS>; num_neighbors(DIMS)]
where [PositionND<DIMS>; num_neighbors(DIMS) + 1]: Sized {
// Day 17 gets 25% faster if we cheat by using these cached vectors
if DIMS < 5 {
return match DIMS {
1 => {
let mut out = [*self; num_neighbors(DIMS)];
for (out, dir) in out.iter_mut().zip(NEIGHBOR_VECTORS_1D.iter()) {
*out = *out + PositionND::from_padded(dir);
}
out
}
2 => {
let mut out = [*self; num_neighbors(DIMS)];
for (out, dir) in out.iter_mut().zip(NEIGHBOR_VECTORS_2D.iter()) {
*out = *out + PositionND::from_padded(dir);
}
out
}
3 => {
let mut out = [*self; num_neighbors(DIMS)];
for (out, dir) in out.iter_mut().zip(NEIGHBOR_VECTORS_3D.iter()) {
*out = *out + PositionND::from_padded(dir);
}
out
}
4 => {
let mut out = [*self; num_neighbors(DIMS)];
for (out, dir) in out.iter_mut().zip(NEIGHBOR_VECTORS_4D.iter()) {
*out = *out + PositionND::from_padded(dir);
}
out
}
_ => unreachable!(),
};
}
let ns = neighbor_vectors::<DIMS>();
let mut out = [*self; num_neighbors(DIMS)];
for (out, dir) in out.iter_mut().zip(IntoIterator::into_iter(ns).filter(|n| n != &[0; DIMS])) {
@ -99,18 +66,6 @@ impl<const DIMS: usize> PositionND<DIMS> {
}
}
fn build_neighbor_cache<const D: usize>() -> Vec<[i64; D]>
where [(); num_neighbors(D) + 1]: {
IntoIterator::into_iter(neighbor_vectors::<D>()).filter(|n| n != &[0; D]).collect()
}
lazy_static! {
static ref NEIGHBOR_VECTORS_1D: Vec<[i64; 1]> = build_neighbor_cache::<1>();
static ref NEIGHBOR_VECTORS_2D: Vec<[i64; 2]> = build_neighbor_cache::<2>();
static ref NEIGHBOR_VECTORS_3D: Vec<[i64; 3]> = build_neighbor_cache::<3>();
static ref NEIGHBOR_VECTORS_4D: Vec<[i64; 4]> = build_neighbor_cache::<4>();
}
#[macro_export]
macro_rules! dim {
($d: expr) => {{

View File

@ -1,3 +1,7 @@
#![allow(incomplete_features)]
#![feature(generic_const_exprs)]
#![feature(associated_type_bounds)]
#![feature(test)]
pub mod common;
pub mod teststuff;
pub mod grid;