diff --git a/25/5/main.py b/25/5/main.py new file mode 100644 index 0000000..ffad245 --- /dev/null +++ b/25/5/main.py @@ -0,0 +1,81 @@ +'''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() diff --git a/25/5/test_main.py b/25/5/test_main.py new file mode 100644 index 0000000..b763de2 --- /dev/null +++ b/25/5/test_main.py @@ -0,0 +1,34 @@ +import pytest + +from main import check_fresh, part1, part2 + +test_ranges = [(3, 5), (10, 14), (16, 20), (12, 18)] + + +@pytest.mark.parametrize('given, id_ranges, expected', + [ + (1, test_ranges, False), + (5, test_ranges, True), + (8, test_ranges, False), + (11, test_ranges, True), + (17, test_ranges, True), + (32, test_ranges, False) + ]) +def test_fresh_checker(given, id_ranges, expected): + assert check_fresh(id_ranges, given) == expected + + +@pytest.mark.parametrize('ids, id_ranges, expected', + [ + ([1,5,8,11,17,32], test_ranges, 3) + ]) +def test_part1(ids, id_ranges, expected): + assert part1(id_ranges, ids) == expected + + +@pytest.mark.parametrize('id_ranges, expected', + [ + (test_ranges, 14), + ]) +def test_part2(id_ranges, expected): + assert part2(id_ranges) == expected