Advent of Code 2020 day17
41300 단어 Rustadventofcodetech
part1
.#.
..#
###
과 같은 입력을 제공합니다.#
는active를 나타내고.
는inactive를 나타내며 이 입력 상태에서 모두 inactive로 초기화되어 무한히 확장된 3차원 공간 내의 어느 평면의 위치에만 있다.각 좌표의 cube는 3차원 각 축에서 ±1 이내의 거리
26
개의neighbors 상태에 따라 다음 상태를 결정한다.초기 상태에서 6개의 순환을 거친 후 active cube가 몇 개 있습니까?이런 문제.
6개의 순환으로 확정되면 각 차원의
+
방향, -
방향에서 각각 높이6
까지만 확장되기 때문에 초기 입력이3x3
라면 15x15x13
정도의 공간을 정의하고 그 중에서 계산하면 simultation이 가능하다.예를 들면 이런 느낌.
struct Solution {
grid: Vec<Vec<Vec<bool>>>,
}
impl Solution {
fn new(inputs: Vec<String>) -> Self {
let (x, y) = (inputs[0].len(), inputs.len());
let mut grid = vec![vec![vec![false; x + 12]; y + 12]; 13];
for (i, row) in inputs.iter().enumerate() {
for (j, c) in row.chars().enumerate() {
grid[6][i + 6][j + 6] = c == '#'
}
}
Self { grid }
}
fn solve_1(&self) -> usize {
let mut grid = self.grid.clone();
let mut d: Vec<(i32, i32, i32)> = Vec::with_capacity(26);
for i in -1..=1 {
for j in -1..=1 {
for k in -1..=1 {
if i == 0 && j == 0 && k == 0 {
continue;
}
d.push((i, j, k));
}
}
}
for _ in 0..6 {
grid = grid
.iter()
.enumerate()
.map(|(i, plane)| {
plane
.iter()
.enumerate()
.map(|(j, row)| {
row.iter()
.enumerate()
.map(|(k, &b)| {
let neighbors = d
.iter()
.filter(|&d| {
let z = i as i32 + d.0;
let y = j as i32 + d.1;
let x = k as i32 + d.2;
z >= 0
&& y >= 0
&& x >= 0
&& z < grid.len() as i32
&& y < grid[0].len() as i32
&& x < grid[0][0].len() as i32
&& grid[z as usize][y as usize][x as usize]
})
.count();
match b {
true if neighbors != 2 && neighbors != 3 => false,
false if neighbors == 3 => true,
b => b,
}
})
.collect()
})
.collect()
})
.collect();
}
grid.iter()
.map(|plane| {
plane
.iter()
.map(|row| row.iter().filter(|&&b| b).count())
.sum::<usize>()
})
.sum()
}
}
part2
무한히 넓은 공간이 3차원이 아닌 4차원(!)이라니.마찬가지로 각 비례축이 ±1 이내의 거리에 있는 neighbors는 이번
26
이 아니라 80
개다.상태 마이그레이션의 규칙은 동일합니다.이렇게 하면
Vec<Vec<Vec<bool>>>>
똑같이 대응Vec<Vec<Vec<Vec<bool>>>>>
할 수 있지만 쓸모없는 공간도 늘어나 다른 방법을 시도해 보자.active
에 있는 좌표만 HashSet
를 가지게 합니다.다음active
이 될 수 있는 큐브는 현재active
큐브에서 볼 수 있는neighbors들(+본인)만 있기 때문에 그active
의neighbors의 수량만 확인하면 된다.그리고 처음부터 4차원 좌표를 준비했는데 neighbors의 정의만 3차원과 4차원으로 전환(3차원에서는 시축이 없으면 된다)하면 파트1과 파트2의simultation 논리도 반복적으로 사용할 수 있다.
마지막으로
w
에서 답을 찾습니다.struct Solution {
active: HashSet<(i32, i32, i32, i32)>,
}
impl Solution {
fn new(inputs: Vec<String>) -> Self {
let mut active: HashSet<(i32, i32, i32, i32)> = HashSet::new();
for (i, row) in inputs.iter().enumerate() {
for (j, col) in row.chars().enumerate() {
if col == '#' {
active.insert((i as i32, j as i32, 0, 0));
}
}
}
Self { active }
}
fn solve_1(&self) -> usize {
let mut neighbors = Vec::new();
for x in -1..=1 {
for y in -1..=1 {
for z in -1..=1 {
if !(x == 0 && y == 0 && z == 0) {
neighbors.push((x, y, z, 0));
}
}
}
}
self.simulate(&neighbors)
}
fn solve_2(&self) -> usize {
let mut neighbors = Vec::new();
for x in -1..=1 {
for y in -1..=1 {
for z in -1..=1 {
for w in -1..=1 {
if !(x == 0 && y == 0 && z == 0 && w == 0) {
neighbors.push((x, y, z, w));
}
}
}
}
}
self.simulate(&neighbors)
}
fn simulate(&self, neighbors: &[(i32, i32, i32, i32)]) -> usize {
let mut active = self.active.clone();
for _ in 0..6 {
let mut targets = HashSet::new();
for &p in active.iter() {
targets.insert(p);
for &d in neighbors.iter() {
targets.insert((p.0 + d.0, p.1 + d.1, p.2 + d.2, p.3 + d.3));
}
}
active = targets
.into_iter()
.filter(|&p| {
let count = neighbors
.iter()
.filter(|d| active.contains(&(p.0 + d.0, p.1 + d.1, p.2 + d.2, p.3 + d.3)))
.count();
count == 3 || (count == 2 && active.contains(&p))
})
.collect();
}
active.len()
}
}
Reference
이 문제에 관하여(Advent of Code 2020 day17), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/sugyan/articles/e0efde71031df3텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)