def run() -> (int, int): tiles, tile_edges = {}, {} for tile_info in read_as.groups("input/20.txt"): tile_id = int(re.search("Tile ([0-9]+):", tile_info[0]).groups()[0]) tile = tile_info[1:] tiles[tile_id] = tile edges = [ top_row(tile), right_col(tile), bottom_row(tile), left_col(tile) ] tile_edges[tile_id] = edges matching_edges = set() matches = defaultdict(lambda: defaultdict(list)) for t, other_t in it.product(tile_edges, repeat=2): if other_t != t: for i in range(len(tile_edges[t])): edge = tile_edges[t][i] for j in range(len(tile_edges[other_t])): other_edge = tile_edges[other_t][j] if edge == other_edge or edge == other_edge[::-1]: matches[t][i] = other_t matching_edges.add(edge) corners = [tile for tile in tiles if len(matches[tile]) == 2] prod_corners = math.prod(c for c in corners) # P2 grid = pop_grid(corners[0], tiles, matching_edges, matches) n = int(math.sqrt(len(tiles))) grid_stripped = [] for r in range(n): for sub_r in range(1, len(grid[(0, 0)][1]) - 1): row_str = "" for c in range(n): row_str += grid[(r, c)][1][sub_r][1:-1] grid_stripped.append(row_str) monster = [ " # ", "# ## ## ###", " # # # # # # " ] rollover = len(grid_stripped[0]) - len(monster[0]) monster_regex = "(?=" + ("." * rollover).join(monster).replace(' ', ".") + ")" grid_rots = rot_and_flip_while_cond(grid_stripped, {lambda x: True}) max_monsters = max( [len(re.findall(monster_regex, "".join(g))) for g in grid_rots]) roughness = "".join(grid_stripped).count( "#") - max_monsters * monster_regex.count("#") return (prod_corners, roughness)
def run() -> (int, int): groups = read_as.groups("input/19.txt") rules = {} for line in groups[0]: rule_id, rule_contents = line.split(':') base_rule = re.search(r"\"(.*)\"", rule_contents) if base_rule: letter = base_rule.groups()[0] rules[rule_id] = letter else: rules[rule_id] = "( " + rule_contents.strip() + " )" rules_p1 = rules_to_regex(deepcopy(rules)) rules_p2 = deepcopy(rules) rules_p2["8"] = "( 42 )+" # dirty hack rules_p2[ "11"] = "( 42 31 | 42 42 31 31 | 42 42 42 31 31 31 | 42 42 42 42 31 31 31 31 | 42 42 42 42 42 31 31 31 31 31 | 42 42 42 42 42 42 31 31 31 31 31 31 | 42 42 42 42 42 42 42 31 31 31 31 31 31 31 | 42 42 42 42 42 42 42 42 31 31 31 31 31 31 31 31 | 42 42 42 42 42 42 42 42 42 31 31 31 31 31 31 31 31 31 | 42 42 42 42 42 42 42 42 42 42 31 31 31 31 31 31 31 31 31 31 )" rules_p2 = rules_to_regex(rules_p2) p1 = sum([ re.fullmatch(rules_p1["0"].replace(" ", ''), message) is not None for message in groups[1] ]) p2 = sum([ re.fullmatch(rules_p2["0"].replace(" ", ''), message) is not None for message in groups[1] ]) return (p1, p2)
def run() -> (int, int): answer_sets = [list(map(set, group)) for group in read_as.groups("input/6.txt")] sum_any, sum_all = 0, 0 for answer_set in answer_sets: sum_any += len(set.union(*answer_set)) sum_all += len(set.intersection(*answer_set)) return(sum_any, sum_all)
def run() -> (int, int): lines = [" ".join(group) for group in read_as.groups("input/4.txt")] passports = [ dict(val.split(":") for val in line.split()) for line in lines ] all_fields = [p for p in passports if has_fields(p)] valid_fields = [p for p in passports if has_valid_fields(p)] return len(all_fields), len(valid_fields)
def run() -> (int, int): groups = read_as.groups("input/22.txt") player_cards = [int(n) for n in groups[0][1:]] crab_cards = [int(n) for n in groups[1][1:]] _, winner_hand_p1 = recursive_combat(player_cards, crab_cards, {}, False) _, winner_hand_p2 = recursive_combat(player_cards, crab_cards, {}, True) score_p1 = sum([(i + 1) * n for (i, n) in enumerate(winner_hand_p1[::-1])]) score_p2 = sum([(i + 1) * n for (i, n) in enumerate(winner_hand_p2[::-1])]) return (score_p1, score_p2)
def run() -> (int, int): rules, my_ticket, other_tickets = read_as.groups("input/16.txt") ruleset = {} for rule in rules: name, a, b, c, d = re.search(r"([a-z ]+): (\d+)-(\d+) or (\d+)-(\d+)", rule).groups() ruleset[name] = [range(int(a), int(b) + 1), range(int(c), int(d) + 1)] matches_rule = lambda field, ranges: int(field) in ranges[0] or int( field) in ranges[1] field_valid = lambda field: any( matches_rule(field, ranges) for ranges in ruleset.values()) ticket_valid = lambda ticket: all( field_valid(field) for field in ticket.split(",")) scanning_rate = sum( int(field) for ticket in other_tickets[1:] for field in ticket.split(",") if not field_valid(field)) # P2 valid_other_tickets = [ ticket for ticket in other_tickets[1:] if ticket_valid(ticket) ] rule_indices = { rule: set(i for i in range(len(ruleset))) for rule in ruleset } for valid_ticket in valid_other_tickets: for (index, field) in enumerate(valid_ticket.split(",")): for rule in ruleset: if not (matches_rule(field, ruleset[rule])): rule_indices[rule].remove(index) known_indices = {} for r, v in sorted(rule_indices.items(), key=lambda x: len(x[1])): known_indices[r] = {x for x in v if x not in known_indices.values()}.pop() my_fields = [int(field) for field in my_ticket[1].split(",")] prod_of_fields = prod([ my_fields[index] for rule, index in known_indices.items() if rule.startswith("departure") ]) return (scanning_rate, prod_of_fields)