def puzzle1(input_file) -> int: input_content = get_input_data(input_file) x_pos = 0 y_pos = 0 direction = 0 direction_x = (1, 0, -1, 0) direction_y = (0, -1, 0, 1) for instr in input_content: (cmd, value) = (instr[0], int(instr[1:])) if cmd == 'F': x_pos += (value * direction_x[direction]) y_pos += (value * direction_y[direction]) elif cmd == 'R': direction = (direction + int(value / 90)) % 4 elif cmd == 'L': direction = (direction + int(value / 90) * 3) % 4 elif cmd == 'N': y_pos += value elif cmd == 'S': y_pos -= value elif cmd == 'E': x_pos += value elif cmd == 'W': x_pos -= value return abs(x_pos) + abs(y_pos)
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) color_rules, bag_contain_rules = get_rules(input_content) shiny_gold_bags = [] visited = {} for bag in bag_contain_rules['shiny gold'].keys(): visited[bag] = 1 shiny_gold_bags.append(bag) current_index = 0 while True: if current_index == len(shiny_gold_bags): break current_color = shiny_gold_bags[current_index] if current_color not in bag_contain_rules: current_index += 1 continue for bag in bag_contain_rules[current_color].keys(): if bag == 'shiny gold': current_index += 1 continue if bag not in visited: shiny_gold_bags.append(bag) visited[bag] = 1 current_index += 1 return len(shiny_gold_bags)
def puzzle2(input_file) -> int: input_content = get_input_data(input_file) neighbors = [ coord for coord in itertools.product([-1, 0, 1], repeat=4) if coord != (0, 0, 0, 0) ] grid4d = set() for y, line in enumerate(input_content): for x, ch in enumerate(line): if ch == '#': grid4d.add((x, y, 0, 0)) for _ in range(6): grid4d_copy = set() range_x = get_range(0, grid4d) range_y = get_range(1, grid4d) range_z = get_range(2, grid4d) range_w = get_range(3, grid4d) for coord in itertools.product(range_x, range_y, range_z, range_w): if coord in grid4d: if nbs4(neighbors, grid4d, coord) in (2, 3): grid4d_copy.add(coord) else: if nbs4(neighbors, grid4d, coord) == 3: grid4d_copy.add(coord) grid4d = grid4d_copy return len(grid4d)
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) mask = {} memory = {} for line in input_content: if line.startswith("mask"): mask = {} (_, mask_val) = line.split(" = ") for idx, mask_bit in enumerate(reversed(mask_val)): if mask_bit != 'X': mask[int(idx)] = int(mask_bit) continue (mem, val_str) = line.split(" = ") mem_val = int(mem[4:-1]) val = int(val_str) result_val = val for idx, mask_bit in sorted(mask.items()): result_val = modify_bit(result_val, idx, mask_bit) memory[mem_val] = result_val return sum(memory.values())
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) card_pub_key = int(input_content[0]) door_pub_key = int(input_content[1]) loop_sizes = {} subject_no = 7 loop_size = 0 public_key = 1 while True: if len(loop_sizes) == 2: break if public_key == card_pub_key: loop_sizes['card'] = loop_size if public_key == door_pub_key: loop_sizes['door'] = loop_size public_key *= subject_no public_key %= 20201227 loop_size += 1 subject_no = door_pub_key public_key = 1 for _ in range(loop_sizes['card']): public_key *= subject_no public_key %= 20201227 return public_key
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) foods = [] for line in input_content: (ingredients, allergens) = line.split(' (contains ') ing = set(ingredients.split(' ')) aller = set(allergens[:-1].split(', ')) foods.append((ing, aller)) all_ing = set() all_allerg = set() for ing, aller in foods: all_ing |= ing all_allerg |= aller possible_allergic_ing = {ing: set(all_allerg) for ing in all_ing} count_ings = defaultdict(int) for ings, allergs in foods: for ing in ings: count_ings[ing] += 1 for allerg in allergs: for ing in all_ing: if ing not in ings: possible_allergic_ing[ing].discard(allerg) count = 0 for ing in all_ing: if not possible_allergic_ing[ing]: count += count_ings[ing] return count
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) player = player1 = [] for line in input_content: if 'Player' in line: continue if line == '': player1 = copy.deepcopy(player) player = [] continue player.append(int(line)) player2 = player while len(player1) != 0 and len(player2) != 0: card1 = player1.pop(0) card2 = player2.pop(0) if card1 > card2: player1.append(card1) player1.append(card2) else: player2.append(card2) player2.append(card1) if len(player1) == 0: player = player2 else: player = player1 return sum([i * card for i, card in enumerate(reversed(player), 1)])
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) current_index = 0 visited = {} accumulator = 0 while True: if current_index == len(input_content): return accumulator if current_index in visited: return accumulator instruction = input_content[current_index] (op, offset) = instruction.split(' ') direction = offset[0] offset_val = int(offset[1:]) visited[current_index] = 1 multiplier = 1 if direction == '-': multiplier = -1 if op == 'acc': accumulator += (multiplier * offset_val) if op in ('nop', 'acc'): current_index += 1 continue if op == 'jmp': current_index += (multiplier * offset_val) return accumulator
def puzzle2(input_file) -> int: input_content = get_input_data(input_file) player = player1 = [] for line in input_content: if 'Player' in line: continue if line == '': player1 = copy.deepcopy(player) player = [] continue player.append(int(line)) player2 = player winner = play_game(player1, player2) if winner == 1: player = player1 else: player = player2 return sum([i * card for i, card in enumerate(reversed(player), 1)])
def puzzle2(input_file) -> int: input_content = get_input_data(input_file) color_rules, bag_contain_rules = get_rules(input_content) total_count = get_internal_bags(color_rules, 'shiny gold') return total_count
def puzzle2(input_file) -> int: input_content = get_input_data(input_file) ticket_rules = {} your = False nearby = False your_tickets = [] nearby_tickets = [] for line in input_content: if line == '': continue if line == 'your ticket:': your = True continue if line == 'nearby tickets:': nearby = True continue if not your and not nearby: rule = line.split(":") ranges = rule[1].lstrip().split(' or ') ticket_rules[rule[0]] = [[int(limit) for limit in vals.split('-')] for vals in ranges] continue if your and not nearby: your_tickets = [int(ticket) for ticket in line.split(',')] continue if nearby: nearby_tickets.append([int(ticket) for ticket in line.split(',')]) valid_tickets = [] for ticket_row in nearby_tickets: valid_ticket_row = True for ticket in ticket_row: valid_ticket = False for rules in ticket_rules.values(): if rules[0][0] <= ticket <= rules[0][1] or rules[1][ 0] <= ticket <= rules[1][1]: valid_ticket = True if not valid_ticket: valid_ticket_row = False break if valid_ticket_row: valid_tickets.append(ticket_row) no_of_rules = len(your_tickets) final_cols = get_row_index(no_of_rules, {}, ticket_rules, valid_tickets) product = 1 for index, name in final_cols.items(): if name.startswith('departure '): product *= your_tickets[index] return product
def puzzle2(input_file) -> int: slopes = ((1, 1), (3, 1), (5, 1), (7, 1), (1, 2)) input_content = get_input_data(input_file) product = 1 for (slope_x, slope_y) in slopes: product *= get_tree_count_for_slope(input_content, slope_x, slope_y) return product
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) max_seat_id = 0 for seat_code in input_content: seat_id = get_seat_id(seat_code) if seat_id > max_seat_id: max_seat_id = seat_id return max_seat_id
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) (rules, strings_to_check) = parse_input(input_content) valid_strings = 0 for line in strings_to_check: if len(line) in is_line_valid(rules, '0', line, 0): valid_strings += 1 return valid_strings
def puzzle2(input_file) -> int: input_content = get_input_data(input_file) valid_passwords = 0 for policy in input_content: (char_restriction, character, password) = policy.split(" ") character = character.rstrip(":") (first_index, second_index) = [int(number) - 1 for number in char_restriction.split('-')] if bool(password[first_index] == character) != bool(password[second_index] == character): valid_passwords += 1 return valid_passwords
def puzzle2(input_file) -> int: input_content = get_input_data(input_file) (rules, strings_to_check) = parse_input(input_content) rules['8'] = [['42'], ['42', '8']] rules['11'] = [['42', '31'], ['42', '11', '31']] valid_strings = 0 for line in strings_to_check: if len(line) in is_line_valid(rules, '0', line, 0): valid_strings += 1 return valid_strings
def puzzle2(input_file) -> int: input_content = get_input_data(input_file) foods = [] for line in input_content: (ingredients, allergens) = line.split(' (contains ') ing = set(ingredients.split(' ')) aller = set(allergens[:-1].split(', ')) foods.append((ing, aller)) all_ing = set() all_allerg = set() for ing, aller in foods: all_ing |= ing all_allerg |= aller possible_allergic_ing = {ing: set(all_allerg) for ing in all_ing} for ings, allergs in foods: for allerg in allergs: for ing in all_ing: if ing not in ings: possible_allergic_ing[ing].discard(allerg) fixed_allergic_ing = {} while len(fixed_allergic_ing) < len(all_allerg): new_possible_allergic_ing = possible_allergic_ing for ing, allergs in possible_allergic_ing.items(): if len(allergs) == 1: for allerg in allergs: fixed_allergic_ing[allerg] = ing continue new_allergs = set() for allerg in allergs: if allerg not in fixed_allergic_ing: new_allergs.add(allerg) new_possible_allergic_ing[ing] = new_allergs possible_allergic_ing = new_possible_allergic_ing ing_list = [ fixed_allergic_ing[allerg] for allerg in sorted(fixed_allergic_ing) ] return ','.join(ing_list)
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) sum_expr = 0 for line in input_content: line = line.replace("(", " ( ") line = line.replace(")", " ) ") exprs = line.split(' ') operands = [] operators = [] for expr in exprs: if expr == '': continue if expr in ('+', '*'): if len(operators) > 0 and operators[-1] in ('+', '*'): operator = operators.pop() operand1 = operands.pop() operand2 = operands.pop() if operator == '+': operands.append(operand1 + operand2) if operator == '*': operands.append(operand1 * operand2) operators.append(expr) continue if expr == '(': operators.append('(') continue if expr == ')': while (operator := operators.pop()) != '(': operand1 = operands.pop() operand2 = operands.pop() if operator == '+': operands.append(operand1 + operand2) if operator == '*': operands.append(operand1 * operand2) continue operands.append(int(expr)) while len(operators) > 0 and (operator := operators.pop()) != '(': operand1 = operands.pop() operand2 = operands.pop() if operator == '+': operands.append(operand1 + operand2) if operator == '*': operands.append(operand1 * operand2)
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) time_start = int(input_content[0]) bus_ids = [int(id) for id in input_content[1].split(',') if id.isdigit()] min_wait_time = math.inf bus_to_catch = 0 for bus_id in bus_ids: wait_time = (-1 * time_start) % bus_id if min_wait_time > wait_time: min_wait_time = wait_time bus_to_catch = bus_id return min_wait_time * bus_to_catch
def puzzle2(input_file) -> int: input_content = get_input_data(input_file) seat_map = [0 for _ in range(1024)] for seat_code in input_content: seat_id = get_seat_id(seat_code) seat_map[seat_id] = 1 first_occupant_found = False for seat_id in range(1024): if first_occupant_found and seat_map[seat_id] == 0: return seat_id if seat_map[seat_id] == 1: first_occupant_found = True return 0
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) valid_passwords = 0 for policy in input_content: (char_restriction, character, password) = policy.split(" ") character = character.rstrip(":") char_count = 0 for pass_char in password: if pass_char == character: char_count += 1 (min_chars, max_chars) = [int(number) for number in char_restriction.split('-')] if min_chars <= char_count <= max_chars: valid_passwords += 1 return valid_passwords
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) ticket_rules = {} your = False nearby = False nearby_tickets = [] for line in input_content: if line == '': continue if line == 'your ticket:': your = True continue if line == 'nearby tickets:': nearby = True continue if not your and not nearby: rule = line.split(":") ranges = rule[1].lstrip().split(' or ') ticket_rules[rule[0]] = [[int(limit) for limit in vals.split('-')] for vals in ranges] continue if nearby: nearby_tickets.append([int(ticket) for ticket in line.split(',')]) invalid_tickets = [] for ticket_row in nearby_tickets: for ticket in ticket_row: valid_ticket = False for rules in ticket_rules.values(): if rules[0][0] <= ticket <= rules[0][1] or rules[1][ 0] <= ticket <= rules[1][1]: valid_ticket = True break if not valid_ticket: invalid_tickets.append(ticket) return sum(invalid_tickets)
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) tiles = set() start_tile = (0, 0) dir_map = { 'nw': (0.5, 0.5), 'ne': (-0.5, 0.5), 'sw': (0.5, -0.5), 'se': (-0.5, -0.5), 'e': (-1, 0), 'w': (1, 0) } for line in input_content: path = [] prev = '' for ch in line: if prev in ('n', 's'): direction = prev + ch prev = '' path.append(direction) continue if ch in ('n', 's'): prev = ch continue path.append(ch) current_tile = start_tile for nav in path: current_tile = get_dir(dir_map, nav, current_tile) if current_tile in tiles: tiles.remove(current_tile) else: tiles.add(current_tile) return len(tiles)
def puzzle2(input_file) -> int: input_content = get_input_data(input_file) bus_ids = [ 'x' if bus_id == 'x' else int(bus_id) for bus_id in input_content[1].split(',') ] buses = { bus_id: -idx % bus_id for idx, bus_id in enumerate(bus_ids) if bus_id != 'x' } sorted_ids = list(reversed(sorted(buses))) timestamp = buses[sorted_ids[0]] multiplier = sorted_ids[0] for bus_id in sorted_ids[1:]: while timestamp % bus_id != buses[bus_id]: timestamp += multiplier multiplier *= bus_id return timestamp
def puzzle2(input_file) -> int: input_content = get_input_data(input_file) mask = {} mask_x = {} memory = {} for line in input_content: if line.startswith("mask"): mask = {} mask_x = [] (_, mask_val) = line.split(" = ") for idx, mask_bit in enumerate(reversed(mask_val)): if mask_bit == 'X': mask_x.append(int(idx)) continue mask[int(idx)] = int(mask_bit) continue (mem, val_str) = line.split(" = ") mem_val = int(mem[4:-1]) val = int(val_str) result_addr = mem_val for idx, mask_bit in sorted(mask.items()): if mask_bit == 0: continue result_addr = modify_bit(result_addr, idx, mask_bit) addresses = {result_addr} addresses = modify_floating_bit(result_addr, mask_x, addresses, 0) for addr in addresses: memory[addr] = val return sum(memory.values())
def puzzle1(input_file) -> int: input_content = get_input_data(input_file) return get_tree_count_for_slope(input_content, 3, 1)
def puzzle2(input_file) -> int: input_content = get_input_data(input_file) x_pos = 0 y_pos = 0 waypoint_rel_x = waypoint_x = 10 waypoint_rel_y = waypoint_y = 1 for instr in input_content: (cmd, value) = (instr[0], int(instr[1:])) if cmd == 'F': ship_x = waypoint_rel_x * value ship_y = waypoint_rel_y * value x_pos += ship_x y_pos -= ship_y waypoint_x = x_pos + waypoint_rel_x waypoint_y = x_pos + waypoint_rel_y if cmd == 'R': if value == 90: waypoint_x = x_pos + waypoint_rel_y waypoint_y = y_pos - waypoint_rel_x if value == 180: waypoint_x = x_pos - waypoint_rel_x waypoint_y = y_pos - waypoint_rel_y if value == 270: waypoint_x = x_pos - waypoint_rel_y waypoint_y = y_pos + waypoint_rel_x waypoint_rel_x = waypoint_x - x_pos waypoint_rel_y = waypoint_y - y_pos if cmd == 'L': if value == 270: waypoint_x = x_pos + waypoint_rel_y waypoint_y = y_pos - waypoint_rel_x if value == 180: waypoint_x = x_pos - waypoint_rel_x waypoint_y = y_pos - waypoint_rel_y if value == 90: waypoint_x = x_pos - waypoint_rel_y waypoint_y = y_pos + waypoint_rel_x waypoint_rel_x = waypoint_x - x_pos waypoint_rel_y = waypoint_y - y_pos if cmd == 'N': waypoint_rel_y += value waypoint_y = y_pos + waypoint_rel_y if cmd == 'S': waypoint_rel_y -= value waypoint_y = y_pos + waypoint_rel_y if cmd == 'E': waypoint_rel_x += value waypoint_x = x_pos + waypoint_rel_x if cmd == 'W': waypoint_rel_x -= value waypoint_x = y_pos + waypoint_rel_x return abs(x_pos) + abs(y_pos)
def puzzle2(input_file) -> int: input_content = get_input_data(input_file) return execute_instr(input_content, 0, False, 0, {})
def puzzle2(input_file) -> int: input_content = get_input_data(input_file) tiles = defaultdict(bool) # False = white, True = black start_tile = (0, 0) dir_map = { 'nw': (0.5, 0.5), 'ne': (-0.5, 0.5), 'sw': (0.5, -0.5), 'se': (-0.5, -0.5), 'e': (-1, 0), 'w': (1, 0) } for line in input_content: path = [] prev = '' for ch in line: if prev in ('n', 's'): direction = prev + ch prev = '' path.append(direction) continue if ch in ('n', 's'): prev = ch continue path.append(ch) current_tile = start_tile for nav in path: current_tile = get_dir(dir_map, nav, current_tile) tiles[current_tile] = not tiles[current_tile] for _ in range(100): new_tiles = copy.deepcopy(tiles) for current_tile in tiles: neighbors = get_neighbors(dir_map, current_tile) for neighbor in neighbors: if neighbor not in tiles: new_tiles[neighbor] = False tiles = new_tiles to_be_flipped = {} for tile, color in tiles.items(): neighbors = get_neighbors(dir_map, tile) assert len(neighbors) == 6 black_neighbors = 0 for neighbor in neighbors: if neighbor in tiles and tiles[neighbor]: black_neighbors += 1 if color: # black if black_neighbors == 0 or black_neighbors > 2: to_be_flipped[tile] = False continue if black_neighbors == 2: to_be_flipped[tile] = True for tile, color in to_be_flipped.items(): tiles[tile] = color return list(tiles.values()).count(True)