Add 2020/17/2
This commit is contained in:
parent
a2bee8300b
commit
eef4aa7643
@ -4,24 +4,22 @@ use aoc2020::{
|
||||
common::*, grid::{cell::Cell, *}
|
||||
};
|
||||
|
||||
type Parsed = Grid<Position3D, Cell>;
|
||||
|
||||
fn read_input() -> String {
|
||||
read_file(17)
|
||||
}
|
||||
|
||||
fn parse_input(raw: &str) -> Parsed {
|
||||
fn parse_input<P: Position, F: FnMut((usize, usize)) -> P + Copy>(raw: &str, mut pos_gen: F) -> Grid<P, Cell> {
|
||||
raw.lines()
|
||||
.enumerate()
|
||||
.flat_map(move |(y, l)| l.bytes().enumerate().map(move |(x, b)| ((x, y, 0).into(), b.into())))
|
||||
.flat_map(move |(y, l)| l.bytes().enumerate().map(move |(x, b)| (pos_gen((x, y)), b.into())))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn count_live_neighbors(p: &Position3D, grid: &Parsed) -> usize {
|
||||
fn count_live_neighbors<P: Position>(p: &P, grid: &Grid<P, Cell>) -> usize {
|
||||
p.neighbors().iter().filter(|&n| grid.get(*n) == Cell::Alive).count()
|
||||
}
|
||||
|
||||
fn make_step(input: Parsed) -> Parsed {
|
||||
fn make_step<P: Position>(input: Grid<P, Cell>) -> Grid<P, Cell> {
|
||||
let readonly = input.clone();
|
||||
input
|
||||
.fields
|
||||
@ -39,38 +37,66 @@ fn make_step(input: Parsed) -> Parsed {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn part1(parsed: &Parsed) -> usize {
|
||||
fn solve<P: Position>(parsed: &Grid<P, Cell>, steps: usize) -> usize {
|
||||
let mut clone = parsed.clone();
|
||||
for _ in 0..6 {
|
||||
for _ in 0..steps {
|
||||
clone = make_step(clone);
|
||||
}
|
||||
clone.fields.into_iter().filter(|(_, c)| c == &Cell::Alive).count()
|
||||
}
|
||||
|
||||
fn part2(parsed: &Parsed) -> usize {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input = parse_input(&read_input());
|
||||
println!("Part 1: {}", part1(&input));
|
||||
println!("Part 2: {}", part2(&input));
|
||||
let raw = read_input();
|
||||
let input = parse_input(&raw, |(x, y)| Position3D::from((x, y, 0)));
|
||||
println!("Part 1: {}", solve(&input, 6));
|
||||
let input = parse_input(&raw, |(x, y)| Position4D::from((x, y, 0, 0)));
|
||||
println!("Part 2: {}", solve(&input, 6));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use aoc2020::*;
|
||||
use paste::paste;
|
||||
use test::black_box;
|
||||
|
||||
const TEST_INPUT: &str = ".#.
|
||||
..#
|
||||
###";
|
||||
|
||||
test!(part1() == 112);
|
||||
//test!(part2() == 0);
|
||||
bench!(part1() == 348);
|
||||
//bench!(part2() == 0);
|
||||
// bench_input!(fields == 0);
|
||||
#[test]
|
||||
fn test_3d() {
|
||||
let input = parse_input(TEST_INPUT, |(x, y)| Position3D::from((x, y, 0)));
|
||||
assert_eq!(solve(&input, 6), 112);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_4d() {
|
||||
let input = parse_input(TEST_INPUT, |(x, y)| Position4D::from((x, y, 0, 0)));
|
||||
assert_eq!(solve(&input, 6), 848);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_3d_parse(b: &mut test::Bencher) {
|
||||
let raw = read_input();
|
||||
b.iter(|| assert_eq!(parse_input(black_box(&raw), |(x, y)| Position3D::from((x, y, 0))).fields.len(), 64));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[rustfmt::skip]
|
||||
fn bench_4d_parse(b: &mut test::Bencher) {
|
||||
let raw = read_input();
|
||||
b.iter(|| assert_eq!(parse_input(black_box(&raw), |(x, y)| Position4D::from((x, y, 0, 0))).fields.len(), 64));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_3d(b: &mut test::Bencher) {
|
||||
let input = parse_input(&read_input(), |(x, y)| Position3D::from((x, y, 0)));
|
||||
b.iter(|| assert_eq!(solve(&input, 6), 348));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_4d(b: &mut test::Bencher) {
|
||||
let input = parse_input(&read_input(), |(x, y)| Position4D::from((x, y, 0, 0)));
|
||||
b.iter(|| assert_eq!(solve(&input, 6), 2236));
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use itertools::iproduct;
|
||||
use std::{convert::TryInto, hash::Hash, ops, ops::AddAssign};
|
||||
|
||||
pub trait Position
|
||||
where Self: Sized + Hash + Eq
|
||||
where Self: Sized + Hash + PartialEq + Eq + Clone + Copy
|
||||
{
|
||||
fn neighbors(&self) -> Vec<Self>;
|
||||
}
|
||||
@ -22,6 +22,14 @@ pub struct Position3D {
|
||||
pub z: i64,
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)]
|
||||
pub struct Position4D {
|
||||
pub x: i64,
|
||||
pub y: i64,
|
||||
pub z: i64,
|
||||
pub w: i64,
|
||||
}
|
||||
|
||||
mod p2d {
|
||||
use super::*;
|
||||
|
||||
@ -131,6 +139,50 @@ mod p3d {
|
||||
});
|
||||
}
|
||||
|
||||
mod p4d {
|
||||
use super::*;
|
||||
|
||||
impl Position for Position4D {
|
||||
fn neighbors(&self) -> Vec<Position4D> {
|
||||
iproduct!((-1..=1), (-1..=1), (-1..=1), (-1..=1))
|
||||
.filter(|t| t != &(0, 0, 0, 0))
|
||||
.map(|(x, y, z, w)| *self + Position4D::from((x, y, z, w)))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> From<(I, I, I, I)> for Position4D
|
||||
where I: TryInto<i64>
|
||||
{
|
||||
fn from((x, y, z, w): (I, I, I, I)) -> Position4D {
|
||||
Position4D {
|
||||
x: unwrap_number_result(x),
|
||||
y: unwrap_number_result(y),
|
||||
z: unwrap_number_result(z),
|
||||
w: unwrap_number_result(w),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_op!(-|a: Position4D, b: Position4D| -> Position4D {
|
||||
Position4D {
|
||||
x: a.x - b.x,
|
||||
y: a.y - b.y,
|
||||
z: a.z - b.z,
|
||||
w: a.w - b.w,
|
||||
}
|
||||
});
|
||||
|
||||
impl_op!(+|a: Position4D, b: Position4D| -> Position4D {
|
||||
Position4D {
|
||||
x: a.x + b.x,
|
||||
y: a.y + b.y,
|
||||
z: a.z + b.z,
|
||||
w: a.w + b.w,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// because calling .unwrap() on a TryInto result isn’t possible without trait bounds on the
|
||||
// associated Error type.
|
||||
fn unwrap_number_result<I: TryInto<i64>>(i: I) -> i64 {
|
||||
|
Loading…
Reference in New Issue
Block a user