Advent of Code 2020 day17

41300 단어 Rustadventofcodetech
https://adventofcode.com/2020/day/17

part1


.#.
..#
###
과 같은 입력을 제공합니다.#는active를 나타내고.는inactive를 나타내며 이 입력 상태에서 모두 inactive로 초기화되어 무한히 확장된 3차원 공간 내의 어느 평면의 위치에만 있다.
각 좌표의 cube는 3차원 각 축에서 ±1 이내의 거리26개의neighbors 상태에 따라 다음 상태를 결정한다.
  • 이미 active된 cube는neighbors가 2개 또는 3개의 active인 상황에서만 active를 유지합니다. 그렇지 않으면 inactive
  • 입니다.
  • inactive의cube는neighbors가 3개의activate인 경우만active이고 그렇지 않으면inactive
  • 이런 규칙은 상태를 동시에 이동시킨다.
    초기 상태에서 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()
        }
    }
    

    좋은 웹페이지 즐겨찾기