def part_two(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) seat_ids = sorted([get_seat_id(line) for line in lines]) missing = seat_ids[0] for s in seat_ids: missing ^= s return missing
def part_one(filename: str) -> int: public_keys = read_integers(get_path(__file__, filename)) pub_key1, pub_key2 = public_keys[0], public_keys[1] loop1, loop2 = get_loop_size(pub_key1), get_loop_size(pub_key2) encryption_key = transform(pub_key1, loop2) assert (encryption_key == transform(pub_key2, loop1)) return encryption_key
def part_two(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) area = [[c for c in line] for line in lines] h, w = len(area), len(area[0]) old_area = None while area != old_area: old_area = [[area[r][c] for c in range(w)] for r in range(h)] for r in range(h): for c in range(w): if old_area[r][c] != PATH: occupied = 0 for dr, dc in NEIGHBOURS: nr, nc = r + dr, c + dc # keep moving in same direction till empty or filled seat while 0 <= nr < h and 0 <= nc < w and old_area[nr][nc] != EMPTY_SEAT: if old_area[nr][nc] == FILLED_SEAT: occupied += 1 break nr, nc = nr + dr, nc + dc if occupied == 0: area[r][c] = FILLED_SEAT elif occupied >= 5: area[r][c] = EMPTY_SEAT return sum([x.count(FILLED_SEAT) for x in area])
def part_one(filename: str) -> int: direction = 90 x, y = 0, 0 lines = read_lines(get_path(__file__, filename)) for l in lines: d, v = l[0], int(l[1:]) if d == "R": direction = (direction + v) % 360 if d == "L": direction = (direction - v) % 360 if d == "N": y += v if d == "E": x += v if d == "S": y -= v if d == "W": x -= v if d == "F": y += math.cos(math.radians(direction)) * v x += math.sin(math.radians(direction)) * v return abs(x) + abs(y)
def part_two(filename: str) -> int: wx, wy = 10, 1 sx, sy = 0, 0 lines = read_lines(get_path(__file__, filename)) for l in lines: d, v = l[0], int(l[1:]) if d == "R": wx, wy = rotate_coords(wx, wy, v) if d == "L": wx, wy = rotate_coords(wx, wy, 360 - v) if d == "N": wy += v if d == "E": wx += v if d == "S": wy -= v if d == "W": wx -= v if d == "F": sx += wx * v sy += wy * v return abs(sx) + abs(sy)
def part_one(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) return sum([ int(min_c) <= p.count(l) <= int(max_c) for w in lines for min_c, max_c, l, p in ( re.search(r'(\d+)-(\d+) ([a-z]): ([a-z]+)', w).groups(), ) ])
def part_two(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) memory = {} for line in lines: splitted = line.split("=") key, val = splitted[0].strip(), splitted[1].strip() if key == "mask": mask = val else: address = int(re.search(r'mem\[(\d+)]', key).groups()[0]) address_base = list('{:036b}'.format(address)) floating = 0 # replace with 1's, mark x's with {} for formatting for i in range(BITS): if mask[i] == "X": address_base[i] = "{}" floating += 1 elif mask[i] == "1": address_base[i] = "1" format_address = "".join(address_base) if floating > 0: bin_format = "0{}b".format(floating) # insert each binary number up to 2**floating into positions of X's for i in range(2**floating): mem_address = format_address.format(*format(i, bin_format)) memory[int(mem_address, 2)] = int(val) else: memory[int("".join(format_address), 2)] = int(val) return sum(memory.values())
def part_two(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) recipes = [Recipe(line) for line in lines] matched = get_matching(recipes) ing_list = [matched[k] for k in sorted(matched)] return ",".join(ing_list)
def part_two(filename: str) -> int: ints = read_integers(get_path(__file__, filename)) # use twosum solution from p1 to reduce time complexity from # O(n^3) to O(n^2) for i, n in enumerate(ints): multiplier = two_sum(ints[i + 1:], 2020 - n) if multiplier != -1: return n * multiplier return -1
def part_two(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) trees = [ get_trees(1, 1, lines), get_trees(1, 3, lines), get_trees(1, 5, lines), get_trees(1, 7, lines), get_trees(2, 1, lines) ] return reduce((lambda x, y: x * y), trees)
def part_one(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) earliest, shortest_wait, bus_id = int(lines[0]), float('inf'), None for b in [int(x) for x in lines[1].split(',') if x.isnumeric()]: wait = (((earliest // b) * b) + b) - earliest if wait < shortest_wait: shortest_wait, bus_id = wait, b return shortest_wait * bus_id if shortest_wait else -1
def part_one(filename: str) -> int: ints = read_integers(get_path(__file__, filename)) ints.sort() ones, threes, v = 0, 0, 0 for x in ints: threes += (x - v == 3) ones += (x - v == 1) v = x return ones * (threes + 1)
def part_one(filename: str) -> int: lines = read_raw(get_path(__file__, filename)) pports = lines.split("\n\n") valid_pports = [] for p in pports: valid_fields = 0 for f in p.replace("\n", " ").split(): k, v = f.split(":") valid_fields += k in checks.keys() if valid_fields >= 7: valid_pports.append(p) return len(valid_pports)
def part_two(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) running_product, earliest_bus = 1, 0 # uses chinese remainder theorem for (index, bus) in enumerate(lines[1].split(",")): if bus != "x": while ((earliest_bus + index) % int(bus)) != 0: earliest_bus += running_product running_product *= int(bus) return earliest_bus
def parse_input(filename: str) -> dict: inp = read_raw(get_path(__file__, filename)) splitted = inp.split("\n\n") tiles = [] for tile in splitted: lines = tile.split("\n") id = int(lines[0].split(" ")[1].rstrip(":")) tile = Tile(id, [[x for x in l] for l in lines[1:]]) tile.calc_versions() tiles.append(tile) return tiles
def part_two(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) board = Board_2(lines) for i in range(6): # print("ROUND: {}".format(i)) board.cycle() # board.print() return board.count_alive()
def part_one(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) recipes = [Recipe(line) for line in lines] matched = get_matching(recipes) res = 0 matched_ing = matched.values() for arr in [r.ingredients for r in recipes]: for i in arr: if i not in matched_ing: res += 1 return res
def process_bags(filename) -> dict: lines = read_lines(get_path(__file__, filename)) bags = {} for line in lines: outer_bag, inner_bags = line.split("contain") outer_bag = outer_bag.strip().rstrip("s") bags[outer_bag] = [] if inner_bags != " no other bags.": for bag in inner_bags.split(","): r = re.search(r'(\d+) (\S+.*)', bag.replace(".", "")) if r: num, bag_name = r.groups() bags[outer_bag].append((int(num), bag_name.rstrip("s"))) return bags
def part_two_2(filename: str) -> int: ints = read_integers(get_path(__file__, filename)) ints_set = set(ints) ints.sort() ways = [0] * (max(ints) + 1) for x in [1, 2, 3]: ways[x] = int(x in ints) for i in range(2, max(ints) + 1): if i in ints_set: ways[i] += ways[i - 1] + ways[i - 2] + ways[i - 3] return ways[-1]
def part_two_1(filename: str) -> int: ints = read_integers(get_path(__file__, filename)) ints_set = set(ints) cache = [-1] * max(ints) def number_ways(v): if v not in ints_set: return 0 if v == max(ints): return 1 if cache[v] == -1: cache[v] = sum([number_ways(v + x) for x in range(1, 4)]) return cache[v] return sum([number_ways(x) for x in range(1, 4)])
def part_one(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) memory = {} for line in lines: splitted = line.split("=") key, val = splitted[0].strip(), splitted[1].strip() if key == "mask": mask = val else: address = int(re.search(r'mem\[(\d+)]', key).groups()[0]) val = list('{:036b}'.format(int(val))) for idx, c in enumerate(mask): val[idx] = c if c != "X" else val[idx] memory[address] = int("".join(val), 2) return sum(memory.values())
def part_two(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) for i, line in enumerate(lines): code, value = line.split(" ") if code == "nop": line_copy = lines[:] line_copy[i] = "{} {}".format("jmp", value) completed, acc = run_code(line_copy) if completed: return acc elif code == "jmp": line_copy = lines[:] line_copy[i] = "{} {}".format("nop", value) completed, acc = run_code(line_copy) if completed: return acc return -1
def part_one(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) area = [[c for c in line] for line in lines] h, w = len(area), len(area[0]) old_area = None while area != old_area: old_area = [[area[r][c] for c in range(w)] for r in range(h)] for r in range(h): for c in range(w): if old_area[r][c] != PATH: occupied = 0 for dr, dc in NEIGHBOURS: nr, nc = r + dr, c + dc if 0 <= nr < h and 0 <= nc < w and old_area[nr][nc] == FILLED_SEAT: occupied += 1 if occupied == 0: area[r][c] = FILLED_SEAT elif occupied >= 4: area[r][c] = EMPTY_SEAT return sum([x.count(FILLED_SEAT) for x in area])
def parse_input(filename): lines = read_lines(get_path(__file__, filename)) player1 = deque([int(l) for l in lines[lines.index( "Player 1:") + 1:lines.index("Player 2:") - 1]]) player2 = deque([int(l) for l in lines[lines.index("Player 2:") + 1:]]) return player1, player2
def part_one(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) return get_trees(1, 3, lines)
def part_one(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) black = get_tiles(lines) return len(black)
def part_two(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) black = get_tiles(lines) black = game_of_life(black, 100) return len(black)
def part_one(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) return max([get_seat_id(line) for line in lines])
def part_two(filename: str) -> int: lines = read_lines(get_path(__file__, filename)) return sum([(p[int(pos1) - 1] == l) ^ (p[int(pos2) - 1] == l) for w in lines for pos1, pos2, l, p in ( re.search(r'(\d+)-(\d+) ([a-z]): ([a-z]+)', w).groups(), ) ])
def path(filename: str): return get_path(__file__, filename)