AoC2020/src/bin/day17.rs

112 lines
3.1 KiB
Rust

use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::fs::File;
use std::io::{self, BufRead};
use std::vec::Vec;
#[derive(PartialEq, Copy, Clone, Debug)]
enum CubeState {
Active,
Inactive,
}
fn enumerate_adjacent(x: i32, y: i32, z: i32) -> Vec<(i32, i32, i32)> {
let mut res: Vec<(i32, i32, i32)> = Vec::new();
for dx in -1..2 {
for dy in -1..2 {
for dz in -1..2 {
if dx != 0 || dy != 0 || dz != 0 {
res.push((x + dx, y + dy, z + dz));
}
}
}
}
res
}
fn count_adjacent_active(
x: i32,
y: i32,
z: i32,
world: &HashMap<(i32, i32, i32), CubeState>,
) -> u32 {
enumerate_adjacent(x, y, z)
.iter()
.map(|coords| match world.get(&coords) {
Some(CubeState::Active) => 1,
_ => 0,
})
.fold(0u32, |x, acc| x + acc)
}
fn main() -> Result<(), Box<dyn Error>> {
let file = File::open("inputs/day17.txt")?;
let lines = io::BufReader::new(file).lines().map(|l| l.unwrap());
let mut world: HashMap<(i32, i32, i32), CubeState> = HashMap::new();
let initial_slice: Vec<(i32, i32, i32, CubeState)> = lines
.enumerate()
.map(|(y, l)| {
l.chars()
.enumerate()
.map(|(x, c)| match c {
'#' => (x as i32, y as i32, 0, CubeState::Active),
'.' => (x as i32, y as i32, 0, CubeState::Inactive),
_ => panic!("Unknown State: {}", c),
})
.collect::<Vec<(i32, i32, i32, CubeState)>>()
})
.fold(Vec::new(), |mut acc, mut x| {
acc.append(&mut x);
acc
});
for (x, y, z, s) in initial_slice {
world.insert((x, y, z), s);
}
for _ in 0..6 {
let mut used_positions: HashSet<(i32, i32, i32)> = HashSet::new();
for (x, y, z) in world.keys() {
for coords in enumerate_adjacent(*x, *y, *z) {
used_positions.insert(coords);
}
}
let mut new_world: HashMap<(i32, i32, i32), CubeState> = HashMap::new();
for (x, y, z) in used_positions {
let cur_state = if let Some(state) = world.get(&(x, y, z)) {
*state
} else {
CubeState::Inactive
};
let active_adjacent = count_adjacent_active(x, y, z, &world);
if cur_state == CubeState::Active && (active_adjacent == 2 || active_adjacent == 3) {
new_world.insert((x, y, z), CubeState::Active);
} else if cur_state == CubeState::Inactive && active_adjacent == 3 {
new_world.insert((x, y, z), CubeState::Active);
} else {
new_world.insert((x, y, z), CubeState::Inactive);
};
}
world = new_world;
}
let active_count = world
.values()
.map(|s| match s {
CubeState::Active => 1,
_ => 0,
})
.fold(0, |acc, x| x + acc);
println!("Active Cells: {}", active_count);
Ok(())
}