Solve day 21 and 22 2017.
This commit is contained in:
110
2017/d21.py
Normal file
110
2017/d21.py
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
IMAGE = """.#.
|
||||||
|
..#
|
||||||
|
###"""
|
||||||
|
|
||||||
|
|
||||||
|
def flipv(pattern):
|
||||||
|
return tuple(map(lambda row: tuple(reversed(row)), pattern))
|
||||||
|
|
||||||
|
|
||||||
|
def fliph(pattern):
|
||||||
|
return tuple(reversed(pattern))
|
||||||
|
|
||||||
|
|
||||||
|
def rot90(pattern):
|
||||||
|
return tuple(map(tuple, map(reversed, tuple(zip(*pattern)))))
|
||||||
|
|
||||||
|
|
||||||
|
def parse_rule(line: str) -> dict:
|
||||||
|
lhs, rhs = line.split(" => ")
|
||||||
|
rules = {}
|
||||||
|
lhs = tuple(map(tuple, lhs.split("/")))
|
||||||
|
rhs = list(map(list, rhs.split("/")))
|
||||||
|
|
||||||
|
rules[lhs] = rhs
|
||||||
|
|
||||||
|
rules[rot90(lhs)] = rhs
|
||||||
|
rules[rot90(rot90((lhs)))] = rhs
|
||||||
|
rules[rot90(rot90(rot90((lhs))))] = rhs
|
||||||
|
|
||||||
|
rules[flipv(lhs)] = rhs
|
||||||
|
rules[fliph(lhs)] = rhs
|
||||||
|
|
||||||
|
rules[rot90(flipv(lhs))] = rhs
|
||||||
|
rules[rot90(rot90(flipv(lhs)))] = rhs
|
||||||
|
rules[rot90(rot90(rot90(flipv(lhs))))] = rhs
|
||||||
|
|
||||||
|
rules[rot90(fliph(lhs))] = rhs
|
||||||
|
rules[rot90(rot90(fliph(lhs)))] = rhs
|
||||||
|
rules[rot90(rot90(rot90(fliph(lhs))))] = rhs
|
||||||
|
|
||||||
|
return rules
|
||||||
|
|
||||||
|
|
||||||
|
def print_image(image):
|
||||||
|
for row in image:
|
||||||
|
print("".join(row))
|
||||||
|
|
||||||
|
|
||||||
|
def slice_get(matrix, row, col, size):
|
||||||
|
r = []
|
||||||
|
for ri in range(row, row + size):
|
||||||
|
r.append(matrix[ri][col:col+size])
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def slice_set(matrix, row, col, new):
|
||||||
|
for ri, r in enumerate(new):
|
||||||
|
matrix[ri + row][col:col + len(r)] = r
|
||||||
|
|
||||||
|
|
||||||
|
def slice_append(matrix, slice):
|
||||||
|
for ri, row in enumerate(slice):
|
||||||
|
for c in row:
|
||||||
|
matrix[-len(slice) + ri].append(c)
|
||||||
|
|
||||||
|
|
||||||
|
def part_1(data, iterations=5):
|
||||||
|
rules = {}
|
||||||
|
image = list(map(list, IMAGE.splitlines()))
|
||||||
|
for line in data.splitlines():
|
||||||
|
line = line.strip()
|
||||||
|
for k, v in parse_rule(line).items():
|
||||||
|
assert (k not in rules) or rules[k] == v
|
||||||
|
rules[k] = v
|
||||||
|
|
||||||
|
for _ in range(iterations):
|
||||||
|
len_image = len(image)
|
||||||
|
new_image = []
|
||||||
|
if len_image % 2 == 0:
|
||||||
|
for row in range(0, len(image), 2):
|
||||||
|
for _ in range(3):
|
||||||
|
new_image.append([])
|
||||||
|
for col in range(0, len(image[0]), 2):
|
||||||
|
slice = tuple(map(tuple, slice_get(image, row, col, 2)))
|
||||||
|
new_slice = rules[slice]
|
||||||
|
slice_append(new_image, new_slice)
|
||||||
|
else:
|
||||||
|
for row in range(0, len(image), 3):
|
||||||
|
for _ in range(4):
|
||||||
|
new_image.append([])
|
||||||
|
for col in range(0, len(image[0]), 3):
|
||||||
|
slice = tuple(map(tuple, slice_get(image, row, col, 3)))
|
||||||
|
new_slice = rules[slice]
|
||||||
|
slice_append(new_image, new_slice)
|
||||||
|
image = new_image
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
for row in image:
|
||||||
|
count += row.count("#")
|
||||||
|
print(count)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
data = open(0).read()
|
||||||
|
part_1(data)
|
||||||
|
part_1(data, 18)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
71
2017/d22.py
Normal file
71
2017/d22.py
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
from lib import Grid2D, add2
|
||||||
|
|
||||||
|
|
||||||
|
def part_1(data):
|
||||||
|
steps = 10_000
|
||||||
|
|
||||||
|
g = Grid2D(data)
|
||||||
|
# g.print()
|
||||||
|
dirs = [g.N, g.E, g.S, g.W]
|
||||||
|
|
||||||
|
pos = (g.n_rows // 2, g.n_cols // 2)
|
||||||
|
dir = g.N
|
||||||
|
|
||||||
|
inf = set(g.find("#"))
|
||||||
|
|
||||||
|
burst_inf = 0
|
||||||
|
for _ in range(steps):
|
||||||
|
if pos in inf:
|
||||||
|
# turn right
|
||||||
|
dir = dirs[(dirs.index(dir) + 1) % len(dirs)]
|
||||||
|
inf.remove(pos)
|
||||||
|
else:
|
||||||
|
# turn left
|
||||||
|
dir = dirs[(dirs.index(dir) - 1) % len(dirs)]
|
||||||
|
inf.add(pos)
|
||||||
|
burst_inf += 1
|
||||||
|
pos = add2(pos, dir)
|
||||||
|
print(burst_inf)
|
||||||
|
|
||||||
|
|
||||||
|
def part_2(data):
|
||||||
|
steps = 10000000
|
||||||
|
|
||||||
|
g = Grid2D(data)
|
||||||
|
dirs = [g.N, g.E, g.S, g.W]
|
||||||
|
|
||||||
|
pos = (g.n_rows // 2, g.n_cols // 2)
|
||||||
|
dir = g.N
|
||||||
|
|
||||||
|
weak = set()
|
||||||
|
inf = set(g.find("#"))
|
||||||
|
flagged = set()
|
||||||
|
|
||||||
|
burst_inf = 0
|
||||||
|
for _ in range(steps):
|
||||||
|
if pos in weak:
|
||||||
|
weak.remove(pos)
|
||||||
|
inf.add(pos)
|
||||||
|
burst_inf += 1
|
||||||
|
elif pos in inf:
|
||||||
|
dir = dirs[(dirs.index(dir) + 1) % len(dirs)]
|
||||||
|
inf.remove(pos)
|
||||||
|
flagged.add(pos)
|
||||||
|
elif pos in flagged:
|
||||||
|
dir = dirs[(dirs.index(dir) + 2) % len(dirs)]
|
||||||
|
flagged.remove(pos)
|
||||||
|
else:
|
||||||
|
dir = dirs[(dirs.index(dir) - 1) % len(dirs)]
|
||||||
|
weak.add(pos)
|
||||||
|
pos = add2(pos, dir)
|
||||||
|
print(burst_inf)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
data = open(0).read()
|
||||||
|
part_1(data)
|
||||||
|
part_2(data)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user