Add 2020/17/2
This commit is contained in:
parent
a2bee8300b
commit
eef4aa7643
|
@ -4,24 +4,22 @@ use aoc2020::{
|
||||||
common::*, grid::{cell::Cell, *}
|
common::*, grid::{cell::Cell, *}
|
||||||
};
|
};
|
||||||
|
|
||||||
type Parsed = Grid<Position3D, Cell>;
|
|
||||||
|
|
||||||
fn read_input() -> String {
|
fn read_input() -> String {
|
||||||
read_file(17)
|
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()
|
raw.lines()
|
||||||
.enumerate()
|
.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()
|
.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()
|
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();
|
let readonly = input.clone();
|
||||||
input
|
input
|
||||||
.fields
|
.fields
|
||||||
|
@ -39,38 +37,66 @@ fn make_step(input: Parsed) -> Parsed {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part1(parsed: &Parsed) -> usize {
|
fn solve<P: Position>(parsed: &Grid<P, Cell>, steps: usize) -> usize {
|
||||||
let mut clone = parsed.clone();
|
let mut clone = parsed.clone();
|
||||||
for _ in 0..6 {
|
for _ in 0..steps {
|
||||||
clone = make_step(clone);
|
clone = make_step(clone);
|
||||||
}
|
}
|
||||||
clone.fields.into_iter().filter(|(_, c)| c == &Cell::Alive).count()
|
clone.fields.into_iter().filter(|(_, c)| c == &Cell::Alive).count()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(parsed: &Parsed) -> usize {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let input = parse_input(&read_input());
|
let raw = read_input();
|
||||||
println!("Part 1: {}", part1(&input));
|
let input = parse_input(&raw, |(x, y)| Position3D::from((x, y, 0)));
|
||||||
println!("Part 2: {}", part2(&input));
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use aoc2020::*;
|
use aoc2020::*;
|
||||||
use paste::paste;
|
|
||||||
use test::black_box;
|
use test::black_box;
|
||||||
|
|
||||||
const TEST_INPUT: &str = ".#.
|
const TEST_INPUT: &str = ".#.
|
||||||
..#
|
..#
|
||||||
###";
|
###";
|
||||||
|
|
||||||
test!(part1() == 112);
|
#[test]
|
||||||
//test!(part2() == 0);
|
fn test_3d() {
|
||||||
bench!(part1() == 348);
|
let input = parse_input(TEST_INPUT, |(x, y)| Position3D::from((x, y, 0)));
|
||||||
//bench!(part2() == 0);
|
assert_eq!(solve(&input, 6), 112);
|
||||||
// bench_input!(fields == 0);
|
}
|
||||||
|
|
||||||
|
#[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};
|
use std::{convert::TryInto, hash::Hash, ops, ops::AddAssign};
|
||||||
|
|
||||||
pub trait Position
|
pub trait Position
|
||||||
where Self: Sized + Hash + Eq
|
where Self: Sized + Hash + PartialEq + Eq + Clone + Copy
|
||||||
{
|
{
|
||||||
fn neighbors(&self) -> Vec<Self>;
|
fn neighbors(&self) -> Vec<Self>;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,14 @@ pub struct Position3D {
|
||||||
pub z: i64,
|
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 {
|
mod p2d {
|
||||||
use super::*;
|
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
|
// because calling .unwrap() on a TryInto result isn’t possible without trait bounds on the
|
||||||
// associated Error type.
|
// associated Error type.
|
||||||
fn unwrap_number_result<I: TryInto<i64>>(i: I) -> i64 {
|
fn unwrap_number_result<I: TryInto<i64>>(i: I) -> i64 {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user