add day 17
This commit is contained in:
parent
1a5c98aa4d
commit
5fd6ab1156
5 changed files with 184 additions and 0 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -5,6 +5,7 @@ name = "advent_of_code_2020"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"itertools",
|
||||
"num_enum",
|
||||
]
|
||||
|
||||
|
@ -74,6 +75,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.9.1"
|
||||
|
@ -108,6 +115,15 @@ dependencies = [
|
|||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
|
|
|
@ -9,3 +9,4 @@ edition = "2018"
|
|||
[dependencies]
|
||||
clap = "3.0.0-beta.2"
|
||||
num_enum = "0.5.1"
|
||||
itertools = "0.9.0"
|
||||
|
|
8
input/day17
Normal file
8
input/day17
Normal file
|
@ -0,0 +1,8 @@
|
|||
##.#....
|
||||
...#...#
|
||||
.#.#.##.
|
||||
..#.#...
|
||||
.###....
|
||||
.##.#...
|
||||
#.##..##
|
||||
#.####..
|
157
src/day17.rs
Normal file
157
src/day17.rs
Normal file
|
@ -0,0 +1,157 @@
|
|||
use std::io::BufRead;
|
||||
use std::collections::HashSet;
|
||||
use std::ops::RangeInclusive;
|
||||
use itertools::Itertools;
|
||||
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct PocketDimension {
|
||||
active_cubes: HashSet<Vec<i32>>,
|
||||
bbox: Vec<RangeInclusive<i32>>,
|
||||
}
|
||||
|
||||
impl PocketDimension {
|
||||
fn with_dimension_count(dimensions: usize) -> Self {
|
||||
PocketDimension {
|
||||
active_cubes: HashSet::new(),
|
||||
bbox: (0..dimensions).map(|_| 0..=0).collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn init_from_str(&mut self, s: &str) {
|
||||
self.active_cubes = s.lines()
|
||||
.enumerate()
|
||||
.map(|(line_idx, line)|
|
||||
line.chars()
|
||||
.enumerate()
|
||||
.filter(|(_idx, ch)| *ch == '#')
|
||||
.map(|(idx, _ch)| {
|
||||
let mut cube = vec![0; self.bbox.len()];
|
||||
cube[0] = idx as i32;
|
||||
cube[1] = line_idx as i32;
|
||||
cube
|
||||
}).collect::<HashSet<_>>()
|
||||
).fold(HashSet::new(), |acc, coords| {
|
||||
acc.union(&coords).cloned().collect()
|
||||
});
|
||||
self.update_bbox();
|
||||
}
|
||||
|
||||
fn update_bbox(&mut self) {
|
||||
let mut it = self.active_cubes.iter();
|
||||
let first = it.next().unwrap();
|
||||
|
||||
let mut new_box: Vec<(i32, i32)> = first.iter().map(|c| (*c, *c)).collect();
|
||||
|
||||
for cube in it {
|
||||
for (dimension, coord) in cube.iter().enumerate() {
|
||||
if *coord < new_box[dimension].0 {
|
||||
new_box[dimension].0 = *coord;
|
||||
} else if *coord > new_box[dimension].1 {
|
||||
new_box[dimension].1 = *coord;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (dimension, range) in new_box.iter().enumerate() {
|
||||
self.bbox[dimension] = (range.0 - 1)..=(range.1 + 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn tick(&mut self) {
|
||||
let active_cubes = self.bbox.iter().cloned()
|
||||
.multi_cartesian_product()
|
||||
.filter_map(|cube| {
|
||||
let count = self.neighbours_count(&cube);
|
||||
if self.active_cubes.contains(&cube) && (2..=3).contains(&count) {
|
||||
Some(cube)
|
||||
} else if !self.active_cubes.contains(&cube) && count == 3 {
|
||||
Some(cube)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).collect();
|
||||
self.active_cubes = active_cubes;
|
||||
self.update_bbox()
|
||||
}
|
||||
|
||||
fn neighbours_count(&self, center_cube: &Vec<i32>) -> usize {
|
||||
center_cube.iter().map(|c| (c - 1)..=(c + 1))
|
||||
.multi_cartesian_product()
|
||||
.filter(|cube| cube != center_cube && self.active_cubes.contains(cube))
|
||||
.count()
|
||||
}
|
||||
|
||||
fn simulate(&mut self, cycle_count: usize) {
|
||||
(0..cycle_count).for_each(|_| self.tick());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn part1<F: BufRead> (mut input: F) {
|
||||
let mut buffer = String::new();
|
||||
input.read_to_string(&mut buffer).unwrap();
|
||||
let mut pocket = PocketDimension::with_dimension_count(3);
|
||||
pocket.init_from_str(&buffer);
|
||||
pocket.simulate(6);
|
||||
println!("{}", pocket.active_cubes.len());
|
||||
}
|
||||
|
||||
pub fn part2<F: BufRead> (mut input: F) {
|
||||
let mut buffer = String::new();
|
||||
input.read_to_string(&mut buffer).unwrap();
|
||||
let mut pocket = PocketDimension::with_dimension_count(4);
|
||||
pocket.init_from_str(&buffer);
|
||||
pocket.simulate(6);
|
||||
println!("{}", pocket.active_cubes.len());
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
pub fn test_parse() {
|
||||
let input = ".#.\n..#\n###";
|
||||
let expected = PocketDimension {
|
||||
active_cubes: [vec![1, 0, 0], vec![2, 1, 0], vec![0, 2, 0], vec![1, 2, 0], vec![2, 2, 0]].iter().cloned().collect(),
|
||||
bbox: vec![
|
||||
-1..=3,
|
||||
-1..=3,
|
||||
-1..=1,
|
||||
]
|
||||
};
|
||||
|
||||
let mut pocket = PocketDimension::with_dimension_count(3);
|
||||
pocket.init_from_str(input);
|
||||
assert_eq!(expected, pocket);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_simulate3d() {
|
||||
let mut pocket = PocketDimension {
|
||||
active_cubes: [vec![1, 0, 0], vec![2, 1, 0], vec![0, 2, 0], vec![1, 2, 0], vec![2, 2, 0]].iter().cloned().collect(),
|
||||
bbox: vec![
|
||||
-1..=3,
|
||||
-1..=3,
|
||||
-1..=1,
|
||||
]
|
||||
};
|
||||
pocket.simulate(6);
|
||||
assert_eq!(112, pocket.active_cubes.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_simulate4d() {
|
||||
let mut pocket = PocketDimension {
|
||||
active_cubes: [vec![1, 0, 0, 0], vec![2, 1, 0, 0], vec![0, 2, 0, 0], vec![1, 2, 0, 0], vec![2, 2, 0, 0]].iter().cloned().collect(),
|
||||
bbox: vec![
|
||||
-1..=3,
|
||||
-1..=3,
|
||||
-1..=1,
|
||||
-1..=1,
|
||||
]
|
||||
};
|
||||
pocket.simulate(6);
|
||||
assert_eq!(848, pocket.active_cubes.len());
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ mod day14;
|
|||
mod day14part2;
|
||||
mod day15;
|
||||
mod day16;
|
||||
mod day17;
|
||||
|
||||
fn main() {
|
||||
let matches = App::new("Advent of Code 2020")
|
||||
|
@ -66,6 +67,7 @@ fn main() {
|
|||
day14::part1, day14part2::part2,
|
||||
day15::part1, day15::part2,
|
||||
day16::part1, day16::part2,
|
||||
day17::part1, day17::part2,
|
||||
];
|
||||
|
||||
if let Some(f) = challenges.get(challenge) {
|
||||
|
|
Loading…
Add table
Reference in a new issue