def replace_at_index(s: str, r: str, idx: int) -> str: return s[:idx] + r + s[idx + 1:] def part_a(): decoder = Decoder() for cmd, args in data: decoder.interpret(cmd, args) return decoder.calc_sum() def part_b(): decoder = QuantumDecoder() for cmd, args in data: decoder.interpret(cmd, args) return decoder.calc_sum() def load(): return [(match.group(1), match.groups()[1:]) for line in problem.data() for match in [p.match(line) for p in PATTERNS] if match] if __name__ == '__main__': problem = Problem(14) data = load() problem.submit(part_a(), 'a') # 6513443633260 problem.submit(part_b(), 'b') # 3442819875191
with open('entries.txt', 'w') as fh: for entry in entries.items(): node, children = entry fh.write(f"{node}: {children}\n") def pickle_trees(): entries = parse_nodes(problem.data()) trees = build_trees(entries) with open('trees.pkl', 'wb') as fh: pkl.dump(trees, fh) def load(): with open('trees.pkl', 'rb') as fh: return pkl.load(fh) if __name__ == '__main__': problem = Problem(7) # pickle_trees() trees = load() # Collect every 'shiny gold bag' nodes in all trees shiny_gold_bags = list() for tree in trees: find_nodes('shiny gold bag', tree, shiny_gold_bags) problem.submit(part_a(), 'a') # 124 problem.submit(part_b(), 'b') # 34862
def adj(self, ref: Tile) -> list: return [tile for tile in self.tiles.values() if tile.is_adj(*ref.pos)] def part_a(instructions: list): hexgrid = HexGrid() hexgrid.find_and_flip(instructions) return hexgrid.count_color(BLACK) def part_b(instructions: list): hexgrid = HexGrid() hexgrid.find_and_flip(instructions) print(hexgrid.count_color(BLACK)) hexgrid.live(iterations=100) return hexgrid.count_color(BLACK) def load(p: Problem): return [re.findall(PATTERN, instr) for instr in p.data()] if __name__ == '__main__': problem = Problem(24, test=False) # print(part_a(load(problem))) # print(part_b(load(problem))) # problem.submit(part_a(load(problem)), 'a') problem.submit(part_b(load(problem)), 'b')
from src.problem import Problem import itertools def part_a(): comb = itertools.combinations(data, 2) comb = [(a, b) for a, b in comb if a + b == 2020] return comb[0][0] * comb[0][1] def part_b(): comb = itertools.combinations(data, 3) comb = [(a, b, c) for a, b, c in comb if a + b + c == 2020] return comb[0][0] * comb[0][1] * comb[0][2] def load(): return problem.data(dtype=int) if __name__ == '__main__': problem = Problem(1) data = load() problem.submit(part_a(), 'a') # 960075 problem.submit(part_b(), 'b') # 212900130
def part_a(): pocket_dim = np.expand_dims(data, axis=0) for _ in range(6): pocket_dim = convolve_cubes(pocket_dim, KERNEL_3D) return np.count_nonzero(pocket_dim == 1) def part_b(): pocket_dim = np.expand_dims(np.expand_dims(data, axis=0), axis=0) for _ in range(6): pocket_dim = convolve_cubes(pocket_dim, KERNEL_4D) return np.count_nonzero(pocket_dim == 1) def convolve_cubes(grid: np.ndarray, kernel: np.ndarray): c = convolve(grid, kernel) return np.vectorize(lambda elem: elem in [3, 102, 103])(c) def load(): return np.array([list(line) for line in problem.data()]) == '#' if __name__ == '__main__': problem = Problem(17) data = load() problem.submit(part_a(), 'a') # 295 problem.submit(part_b(), 'b') # 1972
def part_a(): for i, num in enumerate(data[26:]): preamble = data[i:26 + i] if num not in [sum(pair) for pair in it.combinations(preamble, 2)]: return num def part_b(): for start, _ in enumerate(data): for end, acc in enumerate(it.accumulate(data[start:]), start): if acc == invalid_num: return min(data[start:end]) + max(data[start:end]) if acc > invalid_num: break def load(): return problem.data(dtype=int) if __name__ == '__main__': problem = Problem(9) data = load() invalid_num = part_a() problem.submit(invalid_num, 'a') # 85848519 problem.submit(part_b(), 'b') # 13414198
# Diagonal up-left for r, c in zip(reversed(range(0, r0)), reversed(range(0, c0))): if seats[r][c] == OCCUPIED: n += 1 break if seats[r][c] == FREE: break # Diagonal down-left for r, c in zip(range(r0 + 1, len(seats)), reversed(range(0, c0))): if seats[r][c] == OCCUPIED: n += 1 break if seats[r][c] == FREE: break # Diagonal up-right for r, c in zip(reversed(range(0, r0)), range(c0 + 1, len(seats[0]))): if seats[r][c] == OCCUPIED: n += 1 break if seats[r][c] == FREE: break return n if __name__ == '__main__': problem = Problem(11) data = load() problem.submit(part_a(), 'a') # 2243 problem.submit(part_b(), 'b') # 2027
"W": lambda u, ship: ship.move_waypoint(Cardinal.WEST, u), "L": lambda d, ship: ship.turn_waypoint(Direction.LEFT, d), "R": lambda d, ship: ship.turn_waypoint(Direction.RIGHT, d), "F": lambda u, ship: ship.forward_waypoint(u)} def part_a(): ship = Ship() for instr, param in data: INSTRUCTIONS_A[instr](param, ship) return abs(ship.position[0]) + abs(ship.position[1]) def part_b(): ship = Ship() for instr, param in data: INSTRUCTIONS_B[instr](param, ship) return abs(ship.position[0]) + abs(ship.position[1]) def load(): return [(i[0], int(i[1:])) for i in problem.data()] if __name__ == '__main__': problem = Problem(12) data = load() problem.submit(part_a(), 'a') # 1032 problem.submit(part_b(), 'b') # 156735
if all(rules[r](ticket.split(',')[pos]) for ticket in tickets): if unique_rule: # If more then one rule applies to the position, skip the position unique_rule = None break unique_rule = (r, pos) # If unique rule was found, return it if unique_rule: return unique_rule def load(): data = problem.data() your_ticket = data.index('your ticket:') nearby_tickets = data.index('nearby tickets:') return [ data[:your_ticket - 1], data[your_ticket + 1], data[nearby_tickets + 1:] ] if __name__ == '__main__': problem = Problem(16) data = load() rules = {(m := RULE_PATTERN.match(line)).group(1): _rule_closure(m.group(2), m.group(3), m.group(4), m.group(5)) for line in data[0]} problem.submit(part_a(), 'a') # 20091 problem.submit(part_b(), 'b') # 2325343130651
def part_a(): return sum([ len(answer) for answer in [ set([answer for person in group.split('\n') for answer in person]) for group in data ] ]) def part_b(): return sum([ len(answer) for answer in [ set.intersection(*[ set(answer for answer in person) for person in group.split('\n') ]) for group in data ] ]) def load(): return problem.data(delim='\n\n') if __name__ == '__main__': problem = Problem(6) data = load() problem.submit(part_a(), 'a') # 6625 problem.submit(part_b(), 'b') # 3360
occ = password.count(letter) if min_occ <= occ <= max_occ: valid_entries += 1 return valid_entries def part_b(): valid_entries = 0 for entry in data: pos1 = int(entry.split("-")[0]) - 1 pos2 = int(entry.split("-")[1].split(" ")[0]) - 1 letter = entry.split(" ")[1].split(":")[0] password = entry.split(" ")[2] if (password[pos1] == letter) ^ (password[pos2] == letter): valid_entries += 1 return valid_entries def load(): return problem.data() if __name__ == '__main__': problem = Problem(2) data = load() problem.submit(part_a(), 'a') # 600 problem.submit(part_b(), 'b') # 245
term = self._expr() self._check(Token.Kind.rpar) else: raise RuntimeError("Term must be called with number or lpar token") return term def part_a(data: str): parser = LRParser(data) for _ in range(len(data.split('\n'))): parser.parse() return sum(parser.results) def part_b(data: str): parser = PunstriParser(data) for _ in range(len(data.split('\n'))): parser.parse() return sum(parser.results) def load(p: Problem): return p.raw_data() if __name__ == '__main__': problem = Problem(18) problem.submit(part_a(load(problem)), 'a') # 8929569623593 problem.submit(part_b(load(problem)), 'b') # 231235959382961
return False elif key == 'hcl': if value[0] == '#': rgb = value[1:] for c in rgb: if not (c.isdigit() or 'a' <= c <= 'f'): return False else: return False elif key == 'ecl': if value not in ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth']: return False elif key == 'pid': if len(value) != 9: return False elif key == 'cid': pass # ignore cid return True def load(): return problem.data(delim='\n\n') if __name__ == '__main__': problem = Problem(4) data = load() problem.submit(part_a(), 'a') # 210 problem.submit(part_b(), 'b') # 131
row_area = binary_partitioning(row_area, row_action) for col_action in col_actions: col_area = binary_partitioning(col_area, col_action) assert row_area[0] == row_area[1] assert col_area[0] == col_area[1] return row_area[0], col_area[0] def binary_partitioning(area, action): lower = area[0] upper = area[1] middle = int((upper + lower) / 2) if action == 'F' or action == 'L': return [lower, middle] if action == 'B' or action == 'R': return [middle + 1, upper] def load(): return problem.data() if __name__ == '__main__': problem = Problem(5) data = load() problem.submit(part_a(), 'a') # 974 problem.submit(part_b(), 'b') # 646