def part_one(): target_weight = sum(data) // 3 largest = max(data) for x in range(largest ) print(target_weight) return def part_two(): return if __name__ == '__main__': run_with_timer(part_one) # run_with_timer(part_two) #
dist = float('inf') if is_min else float('-inf') curr_dist = 0 for next_city in city_map[start_city]: if next_city not in visited_cities: curr_dist = city_map[start_city][next_city] + traverse_map( city_map, next_city, visited_cities.copy(), is_min) if (is_min and curr_dist < dist) or (not is_min and curr_dist > dist): dist = curr_dist return dist if curr_dist > 0 else 0 def part_one(): city_map = build_city_graph() return min( traverse_map(city_map, start_city, [], True) for start_city in city_map) def part_two(): city_map = build_city_graph() return max( traverse_map(city_map, start_city, [], False) for start_city in city_map) if __name__ == '__main__': run_with_timer(part_one) # 251 -- took 208 ms run_with_timer(part_two) # 898 -- took 197 ms
for _ in range(num_phases): result[-1] = input_signal[-1] for j in range(len(input_signal) - 2, len(input_signal) // 2, -1): result[j] = (input_signal[j] + result[j + 1]) % 10 input_signal = list(result) result = [0] * len(input_signal) return int(''.join(str(x) for x in input_signal[offset:offset + 8])) def calculate_output_value(input_signal, row_num): if row_num >= len(input_signal) // 2: return abs(sum(int(x) for x in input_signal[row_num - len(input_signal):])) % 10 else: i = row_num total = 0 multiplier = 1 while i < len(input_signal): for j in range(row_num + 1): if i + j < len(input_signal): total += input_signal[i + j] * multiplier else: break i += 2 * (row_num + 1) multiplier *= -1 return abs(total) % 10 if __name__ == '__main__': run_with_timer(part_one) # 58100105 run_with_timer(part_two) # 41781287
def part_one(): molecule, molmap = get_data_as_molecule_map() return replacement_step(molecule, molmap) def f(start, target, molmap, depth): if len(start) > len(target): return None elif start == target: return depth curr_min = 999999999 for i in range(len(start)): for j in molmap[start[i]]: next_val = f(start[:i] + j + start[i + 1:], target, molmap, depth + 1) if next_val: curr_min = min(curr_min, next_val) return curr_min def part_two(): molecule = get_elems(data[-1]) molmap = get_data_as_molecule_map() if __name__ == '__main__': run_with_timer(part_one) # 509 -- took 0 ms run_with_timer(part_two) #
for y_init in range(yrange, -yrange, -1): y = 0 x = 0 curr_x_velocity = x_init curr_y_velocity = y_init while y >= region["ye"] and x <= region["xe"]: if curr_x_velocity == 0 and x < region["xs"]: break x += curr_x_velocity y += curr_y_velocity if region["xs"] <= x <= region["xe"] and region["ys"] >= y >= region["ye"]: valid_coords.append({"x": x_init, "y": y_init}) break curr_y_velocity -= 1 curr_x_velocity -= 1 if curr_x_velocity > 0 else 0 return valid_coords def part_one(): maxy = int(abs(region["ye"]))-1 return maxy * (maxy + 1) // 2 def part_two(): return len(get_valid_initial_velocities()) if __name__ == '__main__': run_with_timer(part_one) # 12561 -- took 0 ms run_with_timer(part_two) # 3785 -- took 90 ms
card_public_key, door_public_key = [ int(x.strip()) for x in open("input.txt").readlines() ] def transform_val(val, subject_number): return (val * subject_number) % 20201227 def part_one(): subject_number = 7 door_loop_size = 0 val = 1 while val != door_public_key: val = transform_val(val, subject_number) door_loop_size += 1 val = 1 for _ in range(door_loop_size): val = transform_val(val, card_public_key) return val def part_two(): return 0 if __name__ == '__main__': run_with_timer(part_one) # 18329280 -- took 4313 ms run_with_timer(part_two) # 0 -- took 0 ms
start = [int(x) for x in vent[0].split(',')] end = [int(x) for x in vent[1].split(',')] if start[0] == end[0]: for x in range(min(start[1], end[1]), max(start[1], end[1]) + 1): floor_map[start[0]][x] += 1 elif start[1] == end[1]: for x in range(min(start[0], end[0]), max(start[0], end[0]) + 1): floor_map[x][start[1]] += 1 elif include_diagonals: xdir = -1 if start[0] > end[0] else 1 ydir = -1 if start[1] > end[1] else 1 for x in range(abs(start[0] - end[0]) + 1): floor_map[start[0] + (xdir * x)][start[1] + (ydir * x)] += 1 return floor_map def part_one(): floor_map = mark_vents(False) return sum(1 for x in floor_map for y in x if y > 1) def part_two(): floor_map = mark_vents(True) return sum(1 for x in floor_map for y in x if y > 1) if __name__ == '__main__': run_with_timer(part_one) # 7468 -- took 57 ms run_with_timer(part_two) # 22364 -- took 76 ms
curr_count = 0 new_str = '' for x in input_val: if int(x) != last_num: if curr_count > 0: new_str += str(curr_count) + str(last_num) last_num = int(x) curr_count = 0 curr_count += 1 new_str += str(curr_count) + str(last_num) return new_str def part_one(): new_val = data for x in range(40): new_val = look_and_say(new_val) return len(new_val) def part_two(): new_val = data for x in range(50): new_val = look_and_say(new_val) return len(new_val) if __name__ == '__main__': run_with_timer(part_one) # 492982 -- took 1248 ms run_with_timer(part_two) # 6989950 -- took 22484 ms
"die": 1, "turn": 1, "p1": { "num": 1, "score": 0, "pos": data[0] }, "p2": { "num": 2, "score": 0, "pos": data[1] } } while state["p1"]["score"] < 1000 and state["p2"]["score"] < 1000: make_move(state, deterministic_die) return min(state["p1"]["score"], state["p2"]["score"]) * ( (state["turn"] - 1) * 3) def part_two(): # state = {"die": 1, "turn": 1, "p1": {"num": 1, "score": 0, "pos": data[0]}, "p2": {"num": 2, "score": 0, "pos": data[1]}} # while state["p1"]["score"] < 1000 and state["p2"]["score"] < 1000: # make_move(state, deterministic_die) # return min(state["p1"]["score"], state["p2"]["score"]) * ((state["turn"]-1)*3) return if __name__ == '__main__': run_with_timer(part_one) # 512442 -- took 0 ms run_with_timer(part_two) #
def get_next_pass(initial): pw = increment(initial) is_valid = check_pw(pw) while not is_valid: if 'i' in pw: pw = short_cut(pw, 'i') elif 'l' in pw: pw = short_cut(pw, 'l') elif 'o' in pw: pw = short_cut(pw, 'o') else: pw = increment(pw) is_valid = check_pw(pw) return pw def part_one(): return get_next_pass(data) def part_two(): initial = get_next_pass(data) return get_next_pass(initial) if __name__ == '__main__': run_with_timer(part_one) # hepxxyzz -- took 2388 ms run_with_timer(part_two) # heqaabcc -- took 8270 ms
flashed_points.add(p) for neighbor in p.get_neighbors(): neighbor.set_value(neighbor.get_value() + 1) if neighbor.get_value() > 9 and neighbor not in flashed_points: increment_and_flash_neighbors(neighbor, flashed_points) def part_one(): m = Grid(values=data) m.set_neighbors_for_all(True) return sum(take_step(m) for _ in range(1, 101)) def part_two(): m = Grid(values=data) m.set_neighbors_for_all(True) i = 0 while not sum( 1 for row in range(m.get_height()) if len(list(filter(lambda x: x.get_value() != 0, m.get_row( row)))) != 0) == 0: take_step(m) i += 1 return i if __name__ == '__main__': run_with_timer(part_one) # 1675 -- took 46 ms run_with_timer(part_two) # 515 -- took 206 ms
return rem_str, v_total, sum(literals) elif type_id == 1: return rem_str, v_total, math.prod(literals) elif type_id == 2: return rem_str, v_total, min(literals) elif type_id == 3: return rem_str, v_total, max(literals) elif type_id == 5: return rem_str, v_total, 1 if literals[0] > literals[1] else 0 elif type_id == 6: return rem_str, v_total, 1 if literals[0] < literals[1] else 0 elif type_id == 7: return rem_str, v_total, 1 if literals[0] == literals[1] else 0 def convert_hex_to_bin_str(hex_str): return "".join(bin(int(x, 16))[2:].zfill(4) for x in list(hex_str)) def part_one(): return parse_packet(convert_hex_to_bin_str(data))[1] def part_two(): return parse_packet(convert_hex_to_bin_str(data))[2] if __name__ == '__main__': run_with_timer(part_one) # 852 -- took 1 ms run_with_timer(part_two) # 19348959966392 -- took 0 ms
for prop in ticker.keys(): if prop in sue.keys() and ticker[prop] != sue[prop]: match_found = False if match_found: return sues.index(sue) + 1 return def part_two(): sues = get_sues_list() for sue in sues: match_found = True for prop in ticker.keys(): if prop in sue.keys(): if prop in ('cats', 'trees'): if ticker[prop] >= sue[prop]: match_found = False elif prop in ('pomeranians', 'goldfish'): if ticker[prop] <= sue[prop]: match_found = False elif ticker[prop] != sue[prop]: match_found = False if match_found: return sues.index(sue) + 1 return if __name__ == '__main__': run_with_timer(part_one) # 40 -- took 2 ms run_with_timer(part_two) # 241 -- took 1 ms
def part_one(): bag_map = get_bag_map() changed = True initial_bag_set = set() initial_bag_set.add('shiny gold') while changed: changed = False initial_size = len(initial_bag_set) for k, v in bag_map.items(): for bag in bag_map[k].keys(): if bag in initial_bag_set: initial_bag_set.add(k) if len(initial_bag_set) > initial_size: changed = True initial_bag_set.remove('shiny gold') return len(initial_bag_set) def count_bags(bag_map, bag): return 1 + sum(v * count_bags(bag_map, k) for k, v in bag_map[bag].items()) def part_two(): return count_bags(get_bag_map(), 'shiny gold') - 1 if __name__ == '__main__': run_with_timer(part_one) # 185 -- took 2 ms run_with_timer(part_two) # 89084 -- took 2 ms
points_to_switch = [] for point in points_to_check: neighbors = f(seat_map, point[0], point[1]) if not int(seat_map[point[0]][point[1]]) and not any(neighbors): points_to_switch.append(point) elif int(seat_map[point[0]][ point[1]]) and sum(neighbors) >= neighbor_count: points_to_switch.append(point) for point in points_to_switch: seat_map[point[0]][point[1]] = (int(seat_map[point[0]][point[1]]) + 1) % 2 if len(points_to_switch) == 0: break return sum(x for x in seat_map) def part_one(): return run_until_equillibrium(get_immediate_neighbors, [list(x) for x in data], 4) def part_two(): return run_until_equillibrium(get_distanced_neighbors, [list(x) for x in data], 5) if __name__ == '__main__': run_with_timer(part_one) # 2319 -- took 2077 ms run_with_timer(part_two) # 2117 -- took 17833 ms
from aoc_utils import run_with_timer # data will be a list of each line stored as a list in this order: [min, max, letter, password] data = [[int(y[0].split('-')[0]), int(y[0].split('-')[1]), y[1][:-1], y[2]] for y in [x.split() for x in open("input.txt").readlines()]] def part_one(): return sum(1 for x in data if x[0] <= x[3].count(x[2]) <= x[1]) def part_two(): return sum(1 for x in data if (x[3][x[0] - 1] == x[2]) ^ (x[3][x[1] - 1] == x[2])) if __name__ == '__main__': run_with_timer(part_one) # 580 -- took 0 ms run_with_timer(part_two) # 611 -- took 0 ms
if not date_match.match(f['iyr']) or not int(f['iyr']) in range( 2010, 2021): return False if not date_match.match(f['eyr']) or not int(f['eyr']) in range( 2020, 2031): return False if not hgt_match.match(f['hgt']) or ('cm' in f['hgt'] and int( f['hgt'][:-2]) not in range(150, 194)) or ( 'in' in f['hgt'] and int(f['hgt'][:-2]) not in range(59, 77)): return False if not hex_match.match(f['hcl']): return False if f['ecl'] not in ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth']: return False if not pid_match.match(f['pid']): return False return True def part_one(): return sum(1 for x in data if validate_presence(x)) def part_two(): return sum(1 for x in data if validate_presence(x) and validate_data(x)) if __name__ == '__main__': run_with_timer(part_one) # 170 -- took 0 ms run_with_timer(part_two) # 103 -- took 1 ms
(y.islower() and y not in current_path), m[x])) else: for x in m: if last_node in m[x]: m[x].remove(last_node) if len(m[last_node]) > 0: for x in m[last_node]: next_path = current_path.copy() next_path.append(x) count_ways_to_node(copy.deepcopy(m), next_path, full_paths, second_visit) def part_one(): m = build_map() full_paths = set() count_ways_to_node(copy.deepcopy(m), ['start'], full_paths, True) return len(full_paths) def part_two(): m = build_map() full_paths = set() count_ways_to_node(copy.deepcopy(m), ['start'], full_paths, False) return len(full_paths) if __name__ == '__main__': run_with_timer(part_one) # 5252 -- took 433 ms run_with_timer(part_two) # 147784 -- took 12627 ms
else: player2.append(two_card) player2.append(one_card) return False def play_game(player1, player2, game_num): round_num = 0 game_hands = [] while len(player1) > 0 and len(player2) > 0: round_num += 1 if (player1, player2) in game_hands: return 1 game_hands.append((player1.copy(), player2.copy())) play_round(player1, player2, game_num) return 1 if len(player1) > 0 else 2 def part_two(): player1, player2 = get_decks() winner = play_game(player1, player2, 1) winning_hand = player1 if winner == 1 else player2 return sum(i * winning_hand[-i] for i in range(1, len(winning_hand) + 1)) if __name__ == '__main__': run_with_timer(part_one) # 33434 -- took 0 ms run_with_timer(part_two) # 31657 -- took 24304 ms
for tile in black_tiles: tile_neighbors = get_neighbors(tile) adjacent_black_tiles = tile_neighbors.intersection(black_tiles) if len(adjacent_black_tiles) == 0 or len(adjacent_black_tiles) > 2: flip_to_white.add(tile) adjacent_white_tiles = tile_neighbors.difference(black_tiles) for wt in adjacent_white_tiles: if wt not in visited_white_tiles: visited_white_tiles.add(wt) wt_neighbors = get_neighbors(wt) wt_adjacent_black = wt_neighbors.intersection(black_tiles) if len(wt_adjacent_black) == 2: flip_to_black.add(wt) return black_tiles.union(flip_to_black).difference(flip_to_white) def part_one(): return len(get_black_tiles()) def part_two(): black_tiles = get_black_tiles() for i in range(100): black_tiles = perform_flip(black_tiles) return len(black_tiles) if __name__ == '__main__': run_with_timer(part_one) # 512 -- took 9 ms run_with_timer(part_two) # 4120 -- took 1800 ms
from aoc_utils import run_with_timer data = [x.strip() for x in open('input.txt').readlines()] def part_one(): return sum( y.count('\\"') + y.count('\\\\') + ((y.count('\\x') - y.count('\\\\x') + y.count('\\\\\\x')) * 3) + 2 for y in (x[1:-1] for x in data)) def part_two(): return sum(x.count('"') + x.count('\\') + 2 for x in data) if __name__ == '__main__': run_with_timer(part_one) # 1350 -- took 0 ms run_with_timer(part_two) # 2085 -- took 0 ms
if is4d: board[initial_point[0] + x][initial_point[1] + y][depth][depth] = data[x][y] else: board[initial_point[0] + x][initial_point[1] + y][depth] = data[x][y] return board def part_one(): steps = 6 board = initialize_board(steps, False) for i in range(steps): board = run_cycle(board, False) return count_active(board, False) def part_two(): steps = 6 board = initialize_board(steps, True) for i in range(steps): board = run_cycle(board, True) return count_active(board, True) if __name__ == '__main__': run_with_timer(part_one) # 384 -- took 744 ms run_with_timer(part_two) # 2012 -- took 45906 ms
picked_cards = [curr["next"], curr["next"]["next"], curr["next"]["next"]["next"]] # Effectively REMOVE those three elements by updating points to skip over them. curr["next"] = curr["next"]["next"]["next"]["next"] curr["next"]["previous"] = curr # Get the destination cup picked_vals = [x["val"] for x in picked_cards] dest_val = (curr["val"] - 1) % num_cups if dest_val == 0: dest_val = num_cups while dest_val in picked_vals: dest_val = (dest_val - 1) % num_cups if dest_val == 0: dest_val = num_cups dest_cup = cups[dest_val] # Alright, now just adjust pointers to re-insert the picked values. picked_cards[2]["next"] = dest_cup["next"] picked_cards[2]["next"]["previous"] = picked_cards[2] dest_cup["next"] = picked_cards[0] picked_cards[0]["previous"] = dest_cup # NEXT! curr = curr["next"] return cups[1]["next"]["val"] * cups[1]["next"]["next"]["val"] if __name__ == '__main__': run_with_timer(part_one) # 82934675 -- took 0 ms run_with_timer(part_two) # 474600314018 -- took 22712 ms
match_found = None for j in range(len(prior_set) - 1): for k in range(j, len(prior_set)): if prior_set[j] + prior_set[k] == data[i]: match_found = (j, k) if not match_found: return data[i] def part_one(): return find_invalid_number(25) def part_two(): invalid_num = find_invalid_number(25) for i in range(data.index(invalid_num)): curr_sum = data[i] next_idx = i + 1 while curr_sum < invalid_num: curr_sum += data[next_idx] next_idx += 1 if curr_sum == invalid_num: return min(data[i:next_idx]) + max(data[i:next_idx]) if __name__ == '__main__': run_with_timer(part_one) # 1038347917 -- took 35 ms run_with_timer(part_two) # 137394018 -- took 47 ms
new_data.append(new_row) new_rows = [[y + x if y + x <= 9 else y + x - 9 for y in row] for x in range(1, 5) for row in new_data] for row in new_rows: new_data.append(row) return new_data def part_one(): m = Grid(values=data) m.set_neighbors_for_all(False) return a_star(m.get_point(0, 0), m.get_point(m.get_height() - 1, m.get_width() - 1)) # return dijkstra(m, m.get_point(0, 0), m.get_point(m.get_height()-1, m.get_width()-1)) def part_two(): m = Grid(values=get_extended_data()) m.set_neighbors_for_all(False) return a_star(m.get_point(0, 0), m.get_point(m.get_height() - 1, m.get_width() - 1)) # return dijkstra(m, m.get_point(0, 0), m.get_point(m.get_height()-1, m.get_width()-1)) if __name__ == '__main__': run_with_timer(part_one) # 745 -- took 2978 ms run_with_timer(part_two) # 3002 -- took 385831 ms
from aoc_utils import run_with_timer data = [x.strip().split() for x in open("input.txt").readlines()] def part_one(): dist = sum(int(d[1]) for d in data if d[0] == 'forward') depth = sum(int(d[1]) for d in data if d[0] == 'down') - sum(int(d[1]) for d in data if d[0] == 'up') return dist * depth def part_two(): curr_depth = 0 curr_dist = 0 curr_aim = 0 for d in data: match d[0]: case 'forward': curr_dist += int(d[1]) curr_depth += curr_aim * int(d[1]) case 'down': curr_aim += int(d[1]) case 'up': curr_aim -= int(d[1]) return curr_depth * curr_dist if __name__ == '__main__': run_with_timer(part_one) # 1660158 -- took 0 ms run_with_timer(part_two) # 1604592846 -- took 0 ms
from aoc_utils import run_with_timer data = [int(x.strip()) for x in open("input.txt").readlines()] def part_one(): return next(first * second for i, first in enumerate(data) for second in data[i + 1:] if first + second == 2020) def part_two(): return next(first * second * third for i, first in enumerate(data) for j, second in enumerate(data[i + 1:]) for third in data[j + 1:] if first + second + third == 2020) if __name__ == '__main__': run_with_timer(part_one) # 197451 -- took 0 ms run_with_timer(part_two) # 138233720 -- took 94 ms
from aoc_utils import run_with_timer data = [x.strip() for x in open("input.txt").readlines()] def calc_seat_id(t): return (int(t[:7].replace('F', '0').replace('B', '1'), 2)) * 8 + int( t[-3:].replace('L', '0').replace('R', '1'), 2) def part_one(): return max(calc_seat_id(x) for x in data) def part_two(): seat_ids = [-1] * (128 * 8) for x in data: seat_ids[calc_seat_id(x)] = 1 for i in range(1, len(seat_ids) - 1): if seat_ids[i] == -1 and seat_ids[i - 1] == 1 and seat_ids[i + 1] == 1: return i return None if __name__ == '__main__': run_with_timer(part_one) # 911 -- took 1 ms run_with_timer(part_two) # 629 -- took 1 ms
from aoc_utils import run_with_timer data = open('input.txt').readline().strip().split(" ") def get_fill_order(row, col): tmp = row + col - 2 return (tmp * (tmp+1) // 2) + col def part_one(): fill_order = get_fill_order(int(data[16][:-1]), int(data[18][:-1])) val = 20151125 for i in range(2, fill_order+1): val = (val * 252533) % 33554393 return val def part_two(): return if __name__ == '__main__': run_with_timer(part_one) # run_with_timer(part_two) #
from aoc_utils import run_with_timer data = [int(x) for x in open("input.txt").readline().strip().split(",")] def calculate_total_fish(days): fish = [data.count(x) for x in range(9)] for x in range(days): next_day_fish = [0] * 9 for i, e in enumerate(fish): if i > 0: next_day_fish[i - 1] += e else: next_day_fish[6] += e next_day_fish[8] += e fish = next_day_fish return sum(x for x in fish) def part_one(): return calculate_total_fish(80) def part_two(): return calculate_total_fish(256) if __name__ == '__main__': run_with_timer(part_one) # 386536 -- took 0 ms run_with_timer(part_two) # 1732821262171 -- took 0 ms