-
Notifications
You must be signed in to change notification settings - Fork 0
/
24_challenge.py
115 lines (86 loc) · 3 KB
/
24_challenge.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
from itertools import product
from pathlib import Path
import colorama
import numpy as np
# Prepare colorama to highlight printed solutions.
colorama.init(autoreset=True)
answer_highlight = colorama.Fore.BLUE + colorama.Style.BRIGHT
# Input data.
DEBUG = False
data_dir = Path("data", "day_24")
if DEBUG:
input_data_file = data_dir / "input_test.txt"
else:
input_data_file = data_dir / "input.txt"
instructions = []
with open(input_data_file, "r") as file:
for line in file:
instructions.append(line.rstrip())
def parse_instruction(instruction):
"""Parse the non-deliminated instruction into a list of individual moves."""
parsed_instruction = []
current_instruction = ""
for i in instruction:
if i == "n" or i == "s":
current_instruction = i
else:
parsed_instruction.append(current_instruction + i)
current_instruction = ""
return parsed_instruction
instructions = [parse_instruction(x) for x in instructions]
print(f"there are {len(instructions)} instructions")
if DEBUG:
print("tile flipping instructions")
for instruction in instructions:
print(" " + " ".join(instruction))
print("=" * 40)
# Make a grid with plenty of space.
max_dim = np.max([len(i) for i in instructions]) * 2
grid_width = (max_dim * 2) + 1
tile_grid = np.zeros((grid_width, grid_width))
print(f"grid dim: {tile_grid.shape}")
# The origin to start from each time.
ORIGIN = np.array([max_dim, max_dim])
print(f"origin: {ORIGIN}")
# Map cardinal directions to 2D array.
directions = {
"e": np.array([2, 0]),
"se": np.array([1, -1]),
"sw": np.array([-1, -1]),
"w": np.array([-2, 0]),
"nw": np.array([-1, 1]),
"ne": np.array([1, 1]),
}
#### Puzzle 1 ####
# Flip tiles.
for instruction in instructions:
pos = ORIGIN.copy()
for i in instruction:
pos += directions[i]
if tile_grid[pos[0], pos[1]] == 0:
tile_grid[pos[0], pos[1]] = 1
else:
tile_grid[pos[0], pos[1]] = 0
def total_black_tiles(g):
return int(np.sum(g))
print(answer_highlight + f"number of black tiles: {total_black_tiles(tile_grid)}")
#### Puzzle 2 ####
def count_black_neighbors(m, i, j):
current_value = m[i, j]
sum_neighbors = np.sum([m[i + x[0], j + x[1]] for x in directions.values()])
return current_value, sum_neighbors
N_DAYS = 100
for day in range(1, N_DAYS + 1):
tile_grid_padded = np.pad(tile_grid, pad_width=2)
for i, j in product(range(tile_grid.shape[0]), range(tile_grid.shape[1])):
current_color, num_blacks = count_black_neighbors(
tile_grid_padded, i + 2, j + 2
)
if current_color == 1 and (num_blacks == 0 or num_blacks > 2):
tile_grid[i, j] = 0
elif current_color == 0 and num_blacks == 2:
tile_grid[i, j] = 1
tile_grid = np.pad(tile_grid, pad_width=2)
if day % 10 == 0:
print(f"day {day}: {total_black_tiles(tile_grid)}")
print(answer_highlight + f"number of black tiles: {total_black_tiles(tile_grid)}")