def main(parttwo=False): inp = aoc_utils.input_block_list() count = 0 for group in inp: if parttwo: splitgroup = aoc_utils.filter_empty(group.split("\n")) li1 = set(splitgroup[0]) for line in splitgroup[1:]: li1 = li1.intersection(set(line)) count += len(li1) else: group = group.replace("\n", "") count += len(set(group)) return count
def main(parttwo=False): passports = aoc_utils.input_block_list() valid = 0 for passport in passports: passport = passport.replace("\n", " ") if not all(passport.count(field) == 1 for field in fields): continue # this RegEx is *so* close and yet I'm still getting an off-by-one error somewhere # it outputs 138 when it should be 137 but not exactly sure why if ( parttwo and re.match( r"(?=.*byr:(19[2-9][0-9]|200[1-2]))(?=.*iyr:(201[0-9]|2020))(?=.*eyr:(202[0-9]|2030))(?=.*hgt:(1[5-8][0-9]cm|19[0-3]cm|59in|6[0-9]in|7[0-6]in))(?=.*hcl:#(?:[0-9a-fA-F]{3}){1,2})(?=.*ecl:(amb|blu|brn|gry|grn|hzl|oth))(?=.*pid:\d{9})", passport, ) is None ): continue if parttwo: print(passport) valid += 1 return valid
return list(map(lambda x: list(map(int, x.split())), board.split("\n"))) def filter_minus_ones_from_board(board: list[list[int]]) -> list[list[int]]: return list(map(lambda row: list(filter(lambda x: x != -1, row)), board)) def min_drawn_numbers_for_board( numbers: list[int], board: list[list[int]] ) -> tuple[bool, int, int]: index = 0 while all(sum(row) > -5 for row in board) and all( sum(col) > -5 for col in zip(*board) ): for row in board: if numbers[index] in row: row[row.index(numbers[index])] = -1 index += 1 if [-1, -1, -1, -1, -1] in board: return False, board.index([-1, -1, -1, -1, -1]), index for i, column in enumerate(zip(*board)): if sum(column) == -5: return True, i, index if __name__ == "__main__": numbers_up, *boards_up = aoc_utils.input_block_list() numbers = list(map(int, numbers_up.strip().split(","))) boards = list(map(parse_board, boards_up)) main(numbers, boards)
if pair not in rules: continue # we cannot reset to zero here, as this pair may have been # or will be affected by other substitutions in this iteration pairs[pair] -= count # add appropriately to the two new element-pairs formed pairs[pair[0] + rules[pair]] += count pairs[rules[pair] + pair[1]] += count # admittedly Counter is somewhat ott here, could have used # defaultdict or any other of the myriad of solutions c = Counter() for elements, count in pairs.items(): for element in elements: c[element] += count # adjust for first and last elements which are never changed # these are not double counted so we add one to double count them c[molecule[0]] += 1 c[molecule[-1]] += 1 cmc = c.most_common() print(cmc[0][1] // 2 - cmc[-1][1] // 2) if __name__ == "__main__": main2(*aoc_utils.input_block_list(), 10) main2(*aoc_utils.input_block_list(), 40)
return int(scanner_no[0]), data def gen_deltas(vectors: list[tuple[int, int, int]]): """ for every possible pair of position vectors, calculate the vector between the two. NB: for points A, B both A --> B and B --> A are generated; n * (n - 1) items returned returned in format (delta, (v_start, v_end)) """ yield from ((vector_delta(triple1, triple2), (triple1, triple2)) for triple1, triple2 in itertools.permutations(vectors, 2) if triple1 != triple2) if __name__ == "__main__": data = dict(map(parse_scanner, aoc_utils.input_block_list())) q = queue.Queue() beacons = set() fixed_scanners = {0: 0} scanner_locations = {0: (0, 0, 0)} q.put(0) while not q.empty(): fixed_scanner_no = q.get() fixed_deltas = dict( gen_deltas( map( orientations[fixed_scanners[fixed_scanner_no]], data[fixed_scanner_no],
# dir is one of x or y # number is the coordinate line along which to fold for dir, num in folds: to_remove = set() new_coords = set() for px, py in coords: if dir == "x" and px > num: to_remove.add((px, py)) new_coords.add((num - abs(px - num), py)) elif dir == "y" and py > num: to_remove.add((px, py)) new_coords.add((px, num - abs(py - num))) coords -= to_remove coords |= new_coords if not printed: print(f"Part 1: {len(coords)} points after first fold") printed = True print("#### Part 2: Decipher the 8 characters below") for y in range(max(c[1] for c in coords) + 1): for x in range(max(c[0] for c in coords) + 1): if (x, y) in coords: print("#", end="") else: print(" ", end="") print() if __name__ == "__main__": main(*aoc_utils.input_block_list())
lambda acc, neighbour: (acc * 2) | int(neighbour in lit_pixels) | (infinite_lit and (neighbour[0] < min_x or neighbour[0] > max_x or neighbour[ 1] < min_y or neighbour[1] > max_y)), gen_adjacent_coords((x, y)), 0, ) new_value = algorithm[index] if new_value == 1: new_lit_pixels.add((x, y)) return new_lit_pixels, not infinite_lit if __name__ == "__main__": algorithm_str, image_str = aoc_utils.input_block_list() algorithm = dict((i, int(v == "#")) for i, v in enumerate(algorithm_str)) lit_pixels = set() for y, row in enumerate(image_str.splitlines()): for x, value in enumerate(row): if value == "#": lit_pixels.add((x, y)) infinite_lit = False for _ in range(2): lit_pixels, infinite_lit = main(algorithm, lit_pixels, infinite_lit) print(len(lit_pixels))