diff --git a/src/advent_of_code/year_2025/day_02.py b/src/advent_of_code/year_2025/day_02.py index c00c3fd..2e44830 100644 --- a/src/advent_of_code/year_2025/day_02.py +++ b/src/advent_of_code/year_2025/day_02.py @@ -1,5 +1,6 @@ from advent_of_code.utils.input_handling import read_input +VALID_PARTS = (1,2) def parse_input(raw): raw_split = raw[0].split(",") @@ -24,26 +25,44 @@ def check_id_valid(id): else: return True - -def get_invalid_ids_in_range(range_pair): +def check_id_valid_v2(id): + id_len = len(str(id)) + half_len = id_len // 2 + for sub_str_len in range(1,half_len+1): + sub_str = id[:sub_str_len] + str_to_search = id[sub_str_len:] + if (len(str_to_search) % sub_str_len == 0): # substr divisible by search str length + if (sub_str * (id_len // sub_str_len) == id): # substr matches N * search string + return False + return True + +def get_invalid_ids_in_range(range_pair, part): full_range = range(range_pair[0], range_pair[1] + 1) + + if part == 1: + id_checker_function = check_id_valid + elif part == 2: + id_checker_function = check_id_valid_v2 + else: + raise ValueError("Specify a valid part number") + invalid_ids = [] for x in full_range: - if not check_id_valid(str(x)): + if not id_checker_function(str(x)): invalid_ids.append(x) return invalid_ids -def find_invalid_ids_in_range_string(range_string): +def find_invalid_ids_in_range_string(range_string, part): range_pair_as_ints = convert_range_string_to_pair(range_string) - invalid_ids_in_range = get_invalid_ids_in_range(range_pair_as_ints) + invalid_ids_in_range = get_invalid_ids_in_range(range_pair_as_ints, part) return invalid_ids_in_range -def find_all_invalid_ids(parsed_input): +def find_all_invalid_ids(parsed_input, part): invalid_ids = [] for range_pair in parsed_input: - invalid_ids.extend(find_invalid_ids_in_range_string(range_pair)) + invalid_ids.extend(find_invalid_ids_in_range_string(range_pair, part)) return invalid_ids @@ -51,14 +70,17 @@ def sum_invalid_ids(invalid_ids): return sum(invalid_ids) -def solve_part_1(parsed_input): - invalid_ids = find_all_invalid_ids(parsed_input) +def solve_part(parsed_input, part): + invalid_ids = find_all_invalid_ids(parsed_input, part) return sum_invalid_ids(invalid_ids) +def solve_part_2(parsed_input): + invalid_ids = find_all_invalid_ids(parsed_input) + return sum_invalid_ids(invalid_ids) def solve(parsed_input): - part_1_solution = solve_part_1(parsed_input) - part_2_solution = None + part_1_solution = solve_part(parsed_input, part=1) + part_2_solution = solve_part(parsed_input, part=2) return (part_1_solution, part_2_solution) diff --git a/tests/year_2025/test_day_02.py b/tests/year_2025/test_day_02.py index 0bedd41..44098e3 100644 --- a/tests/year_2025/test_day_02.py +++ b/tests/year_2025/test_day_02.py @@ -2,6 +2,7 @@ from advent_of_code.year_2025.day_02 import ( check_id_valid, + check_id_valid_v2, convert_range_string_to_pair, find_invalid_ids_in_range_string, parse_input, @@ -17,7 +18,7 @@ [ "11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124" # noqa: E501 ], - (1227775554, None), + (1227775554, 4174379265), ], ], ) @@ -28,6 +29,36 @@ def test_solver(input, expected_output): result = solve(input_parsed) assert result == expected_output +# 11-22 still has two invalid IDs, 11 and 22. +# 95-115 now has two invalid IDs, 99 and 111. +# 998-1012 now has two invalid IDs, 999 and 1010. +# 1188511880-1188511890 still has one invalid ID, 1188511885. +# 222220-222224 still has one invalid ID, 222222. +# 1698522-1698528 still contains no invalid IDs. +# 446443-446449 still has one invalid ID, 446446. +# 38593856-38593862 still has one invalid ID, 38593859. +# 565653-565659 now has one invalid ID, 565656. +# 824824821-824824827 now has one invalid ID, 824824824. +# 2121212118-2121212124 now has one invalid ID, 2121212121. + +@pytest.mark.parametrize( + "input, expected_invalid_ids", + [ + ["11-22", [11, 22]], + ["95-115", [99, 111]], + ["998-1012", [999, 1010]], + ["1188511880-1188511890", [1188511885]], + ["222220-222224", [222222]], + ["1698522-1698528", []], + ["446443-446449", [446446]], + ["38593856-38593862", [38593859]], + ["565653-565659", [565656]], + ["824824821-824824827", [824824824]], + ["2121212118-2121212124", [2121212121]], + ], +) +def test_find_invalid_ids_in_range_string_part_2(input, expected_invalid_ids): + assert expected_invalid_ids == find_invalid_ids_in_range_string(input, part=2) @pytest.mark.parametrize( "input, expected_invalid_ids", @@ -46,7 +77,7 @@ def test_solver(input, expected_output): ], ) def test_find_invalid_ids_in_range_string(input, expected_invalid_ids): - assert expected_invalid_ids == find_invalid_ids_in_range_string(input) + assert expected_invalid_ids == find_invalid_ids_in_range_string(input, part=1) @pytest.mark.parametrize( @@ -74,7 +105,22 @@ def test_convert_range_string_to_pair(input, expected_pair): @pytest.mark.parametrize( "input, is_valid", - [("11", False), ("12", True), ("22", False), ("998", True), ("1010", False)], + [("11", False), ("12", True), ("22", False), ("998", True), ("999", True), ("1010", False), ("565656", True)], ) def test_check_id_valid(input, is_valid): assert is_valid == check_id_valid(input) + +@pytest.mark.parametrize( + "input, is_valid", + [ + ("11", False), + ("12", True), + ("22", False), + ("998", True), + ("999", False), + ("1010", False), + ("565656", False), + ], +) +def test_check_id_valid_v2(input, is_valid): + assert is_valid == check_id_valid_v2(input)