Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 33 additions & 11 deletions src/advent_of_code/year_2025/day_02.py
Original file line number Diff line number Diff line change
@@ -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(",")
Expand All @@ -24,41 +25,62 @@ 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


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)


Expand Down
52 changes: 49 additions & 3 deletions tests/year_2025/test_day_02.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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),
],
],
)
Expand All @@ -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",
Expand All @@ -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(
Expand Down Expand Up @@ -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)