'''AoC Day 5''' import operator def deoverlap(ranges: []) -> []: '''Reduce a list of ranges that may overlap''' new_ranges = [] ranges.sort(key=operator.itemgetter(0)) for r in ranges: found_overlap = False for index, nr in enumerate(new_ranges): if r[0] <= nr[1] and nr[0] <= r[1]: start = min(r[0], nr[0]) end = max(r[1], nr[1]) new_ranges[index] = (start, end) found_overlap = True if found_overlap is False: new_ranges.append(r) else: found_overlap = False return new_ranges def check_fresh(ranges: [], id: int) -> bool: '''Return if a given id is found in any given ranges''' for r in ranges: if id in range(r[0], r[1] + 1): return True return False def part1(ranges: [], ids: []) -> int: '''Part 1, all currently fresh ids''' total = 0 for id in ids: if check_fresh(ranges, id): total += 1 return total def part2(ranges: []) -> int: '''Part 2, all possible fresh ids''' ranges = deoverlap(ranges) fresh_ids = 0 for r in ranges: fresh_ids += len(range(r[0], r[1] + 1)) return fresh_ids def main(): '''Entrypoint''' with open('input.txt', encoding='utf-8') as fh: ranges = [] ids = [] for line in fh: if '-' in line: id_range = line.strip().split('-') ranges.append((int(id_range[0]), int(id_range[1]))) elif line.strip() != '': ids.append(int(line.strip())) freshies = part1(ranges, ids) print(f'Part1: {freshies}') total_fresh = part2(ranges) print(f'Part2: {total_fresh}') if __name__ == "__main__": main()