21.py
1 from lib import * 2 3 input = read_input(2017, 21) 4 5 lines = input.splitlines() 6 7 8 def rotate(p): 9 return tuple("".join(p[j][i] for j in range(len(p))) for i in reversed(range(len(p[0])))) 10 11 12 rules = {} 13 pattern = ".#.", "..#", "###" 14 for line in lines: 15 a, b = [tuple(k.split("/")) for k in line.split(" => ")] 16 rules[a] = b 17 18 19 def find_rule(p): 20 for _ in range(4): 21 if p in rules: 22 return rules[p] 23 p = rotate(p) 24 25 p = tuple(reversed(p)) 26 for _ in range(4): 27 if p in rules: 28 return rules[p] 29 p = rotate(p) 30 31 32 def apply(): 33 k = 3 if len(pattern) % 2 else 2 34 out = [] 35 for i in range(len(pattern) // k): 36 b = [] 37 for j in range(len(pattern) // k): 38 new = find_rule(tuple("".join(pattern[i * k + y][j * k + x] for x in range(k)) for y in range(k))) 39 b.append(new) 40 for line in zip(*b): 41 out.append("".join(line)) 42 return tuple(out) 43 44 45 for _ in range(5): 46 pattern = apply() 47 48 print(sum(line.count("#") for line in pattern)) 49 50 51 rules = {} 52 pattern = ".#.", "..#", "###" 53 for line in lines: 54 a, b = [tuple(k.split("/")) for k in line.split(" => ")] 55 rules[a] = b 56 57 58 def find_rule(p): 59 for _ in range(4): 60 if p in rules: 61 return rules[p] 62 p = rotate(p) 63 p = tuple(reversed(p)) 64 for _ in range(4): 65 if p in rules: 66 return rules[p] 67 p = rotate(p) 68 69 70 def apply(): 71 k = 3 if len(pattern) % 2 else 2 72 out = [] 73 for i in range(len(pattern) // k): 74 b = [] 75 for j in range(len(pattern) // k): 76 new = find_rule(tuple("".join(pattern[i * k + y][j * k + x] for x in range(k)) for y in range(k))) 77 b.append(new) 78 for line in zip(*b): 79 out.append("".join(line)) 80 return tuple(out) 81 82 83 for _ in range(18): 84 pattern = apply() 85 86 print(sum(line.count("#") for line in pattern))