From faaa50240d205a4ded3e3c026417ac2f16d7bfe5 Mon Sep 17 00:00:00 2001 From: Stefan Harmuth Date: Thu, 17 Dec 2020 07:34:46 +0100 Subject: [PATCH] day17: just count active neighbours when there is actually an active neighbour --- day17.py | 121 ++++++++++++++++++------------------------------------- 1 file changed, 39 insertions(+), 82 deletions(-) diff --git a/day17.py b/day17.py index 4f8fe8d..31937d7 100644 --- a/day17.py +++ b/day17.py @@ -7,102 +7,59 @@ TEST_SOLUTION_PART1 = 112 TEST_SOLUTION_PART2 = 848 -def getEdgeCoords(grid, quad=False): - x_list = [x[0] for x in grid.keys()] - y_list = [x[1] for x in grid.keys()] - z_list = [x[2] for x in grid.keys()] - if not quad: - return min(x_list), min(y_list), min(z_list), max(x_list), max(y_list), max(z_list) - else: - w_list = [x[3] for x in grid.keys()] - return min(x_list), min(y_list), min(z_list), min(w_list), max(x_list), max(y_list), max(z_list), max(w_list) +def simulate(active_cubes, fourD=False): + active_neighbours = defaultdict(int) + for active_cube in active_cubes: + if fourD: + x, y, z, w = active_cube + else: + x, y, z = active_cube - -def simulate(grid): - minX, minY, minZ, maxX, maxY, maxZ = getEdgeCoords(grid) - - new_grid = defaultdict(int) - - for x in range(minX - 1, maxX + 2): - for y in range(minY - 1, maxY + 2): - for z in range(minZ - 1, maxZ + 2): - cube_state = grid[(x, y, z)] - - sum_neighbours = 0 - for cx in [x - 1, x, x + 1]: - for cy in [y - 1, y, y + 1]: - for cz in [z - 1, z, z + 1]: - sum_neighbours += grid[(cx, cy, cz)] - - sum_neighbours -= cube_state - - if not cube_state and sum_neighbours == 3: - new_grid[(x, y, z)] = 1 - elif cube_state: - if sum_neighbours not in [2, 3]: - new_grid[(x, y, z)] = 0 + for cx in [x - 1, x, x + 1]: + for cy in [y - 1, y, y + 1]: + for cz in [z - 1, z, z + 1]: + if not fourD: + if not (x == cx and y == cy and z == cz): + active_neighbours[(cx, cy, cz)] += 1 else: - new_grid[(x, y, z)] = 1 + for cw in [active_cube[3] - 1, active_cube[3], active_cube[3] + 1]: + if not (x == cx and y == cy and z == cz and w == cw): + active_neighbours[(cx, cy, cz, cw)] += 1 - return new_grid + new_active_cubes = set() + for coord, neighbour_count in active_neighbours.items(): + if coord in active_cubes and neighbour_count in (2, 3): + new_active_cubes.add(coord) + elif neighbour_count == 3: + new_active_cubes.add(coord) + + return new_active_cubes -def simulate4D(grid): - minX, minY, minZ, minW, maxX, maxY, maxZ, maxW = getEdgeCoords(grid, True) +def get_active_cubes_from_input(grid_input, dimensions=3): + active_cubes = set() + for x, line in enumerate(grid_input): + for y, char in enumerate(line): + if char == '#': + active_cubes.add((x, y) + tuple(0 for _ in range(dimensions - 2))) - new_grid = defaultdict(int) - - for x in range(minX - 1, maxX + 2): - for y in range(minY - 1, maxY + 2): - for z in range(minZ - 1, maxZ + 2): - for w in range(minW - 1, maxW + 2): - cube_state = grid[(x, y, z, w)] - - sum_neighbours = 0 - for cx in [x - 1, x, x + 1]: - for cy in [y - 1, y, y + 1]: - for cz in [z - 1, z, z + 1]: - for cw in [w - 1, w, w + 1]: - sum_neighbours += grid[(cx, cy, cz, cw)] - - sum_neighbours -= cube_state - - if not cube_state and sum_neighbours == 3: - new_grid[(x, y, z, w)] = 1 - elif cube_state: - if sum_neighbours not in [2, 3]: - new_grid[(x, y, z, w)] = 0 - else: - new_grid[(x, y, z, w)] = 1 - - return new_grid + return active_cubes def part1(test_mode=False): my_input = aoclib.getInputAsArray(day=DAY, test=test_mode) + active_cubes = get_active_cubes_from_input(my_input) - grid = defaultdict(int) + for _ in range(6): + active_cubes = simulate(active_cubes) - for y, line in enumerate(my_input): - for x, char in enumerate(line): - grid[(x, y, 0)] = 1 if char == '#' else 0 - - for i in range(6): - grid = simulate(grid) - - return sum(grid.values()) + return len(active_cubes) def part2(test_mode=False): my_input = aoclib.getInputAsArray(day=DAY, test=test_mode) + active_cubes = get_active_cubes_from_input(my_input, 4) + for _ in range(6): + active_cubes = simulate(active_cubes, True) - grid = defaultdict(int) - - for y, line in enumerate(my_input): - for x, char in enumerate(line): - grid[(x, y, 0, 0)] = 1 if char == '#' else 0 - - for i in range(6): - grid = simulate4D(grid) - - return sum(grid.values()) + return len(active_cubes)