diff --git a/day_2.py b/day_2.py new file mode 100644 index 0000000..4d539ef --- /dev/null +++ b/day_2.py @@ -0,0 +1,213 @@ +""" +Check numbers in range for repeating patterns, add them together. +""" +import math +from curses import start_color + +# reject odd number of digits in 1 and 2 + + +test_ids = ["11-22", "95-115", "998-1012", "1188511880-1188511890", "222220-222224", " 1698522-1698528", + "446443-446449", "38593856-38593862", "565653-565659", "824824821-824824827", "2121212118-2121212124"] + +def check_and_split(id_range: str) -> tuple[int, int] | None: + """ + split the range (str, "x-y"), return none if invalid IDs (start and end are odd). + Return (start, end), boolean, true if start and end are equal length IDs, false if not. + :param id_range: range as string like '1-10' + :return: tuple ( tuple(start, end), boolean if equal size or not) + """ + start, end = id_range.split("-") + if len(start)%2 and len(end)%2: + return None + elif len(start) == len(end): + return int(start), int(end) + else: + return int(start), int(end) + + +def test_check_and_split(): + assert check_and_split("11-22") == ((11, 22), True) + assert not check_and_split("111-222") + assert check_and_split("9-14") == ((9, 14), False) + +# if second number has more chars than first, do extra step to catch: +# 9-14 -> 11 + +def make_int(l: list): + return int("".join(map(str, l))) + + +def make_list(i: int): + return [int(n) for n in str(i)] + + +def create_tokens(start: int, end: int): + """ + Create a list of ids that are in the range + """ + # keep ids to sum: + elf_ids = [] + + # if start is < 10, round up. No point in checking under 10! + if start < 10: + start = 10 + + # set up starts: + start_id_length = len(str(start)) + start_repeating_length = int(start_id_length/2) + start_half_pattern_list = make_list(start)[0:start_repeating_length] + start_half_pattern_int = make_int(start_half_pattern_list) + + # set up ends: + end_id_length = int(len(str(end))) + end_repeating_length = math.ceil(end_id_length/2) + end_half_pattern_list = make_list(end)[0:end_repeating_length] + end_half_pattern_int = make_int(end_half_pattern_list) + + for half_pattern in range(start_half_pattern_int, end_half_pattern_int + 1): + new_pattern = int(str(half_pattern) + str(half_pattern)) + if start <= new_pattern <= end: + elf_ids.append(new_pattern) + + return elf_ids + + +def test_create_tokens(): + assert create_tokens(11, 22) == [11, 22] + assert create_tokens(95, 115) == [99] + assert create_tokens(998, 1012) == [1010] + assert create_tokens(1188511880, 1188511890) == [1188511885] + assert create_tokens(222220, 222224) == [222222] + assert create_tokens(446443, 446449) == [446446] + assert create_tokens(38593856, 38593862) == [38593859] + assert create_tokens(9, 14) == [11] + + + +def wrap_it_up(ids: list): + ids_to_sum = [] + for id_range in ids: + check = check_and_split(id_range) + if check: + start, end = check + ids_to_sum.extend(create_tokens(start, end)) + print(ids_to_sum) + return sum(ids_to_sum) + + +def test_wrap_it_up(): + actual_sum = wrap_it_up(test_ids) + assert actual_sum == 1227775554 + + +def test_real_data(): + real_input = open('input_day2.txt').read().split(",") + real_output = wrap_it_up(real_input) + print(real_output) + + +def get_tokens(start:int, end:int, multiple:int): + """ + multiple is the small part of the id to be repeated. So in 1000-2000, the multiple of 2 would be 10, 11, 12 etc + :param start: + :param end: + :param multiple: + :return: + """ + ids = [] + length = len(make_list(end)) + how_many_repeats = int(length/multiple) + + start_part_pattern_list = make_list(start)[0:multiple] + start_part_pattern_int = make_int(start_part_pattern_list) + + end_part_pattern_list = make_list(end)[0:multiple] + end_part_pattern_int = make_int(end_part_pattern_list) + + pattern_start = min(start_part_pattern_int, end_part_pattern_int) + pattern_end = max(start_part_pattern_int, end_part_pattern_int) + + for subpattern in range(pattern_start, pattern_end+1): + + for repeats in range(2, how_many_repeats+1): + new_pattern = int(str(subpattern) * repeats) + if start <= new_pattern <= end: + ids.append(new_pattern) + + set_ids = set(ids) + return sorted(list(set_ids)) + + +def test_get_tokens(): + assert get_tokens(11, 22, 1) == [11, 22] + assert get_tokens(95, 115, 1) == [99, 111] + assert get_tokens(998, 1012, 1) == [999] + assert get_tokens(998, 1012, 2) == [1010] + assert get_tokens(1188511880, 1188511890, 5) == [1188511885] + assert get_tokens(222220, 222224, 3) == [222222] + assert get_tokens(1698522,1698528, 1) == [] + assert get_tokens(446443, 446449, 3) == [446446] + assert get_tokens(38593856, 38593862, 4) == [38593859] + assert get_tokens(565653,565659, 2) == [565656] + assert get_tokens(824824821,824824827, 3) == [824824824] + assert get_tokens(2121212118, 2121212124, 2) == [2121212121] + + +def test_actual_input(): + factors = get_factors(10) + for factor in factors: + print(get_tokens(6948, 9419, factor)) + + +def get_factors(number: int): + factors = [] + for i in range(1, number): + if number % i == 0: + factors.append(i) + return factors + + + +def test_get_highest_factor(): + assert max(get_factors(10)) == 5 + assert max(get_factors(100)) == 50 + assert max(get_factors(1428)) == 714 + + +def wrap_it_up_part_two(ids: list): + ids_to_sum = [] + for id_range in ids: + bad_ids_in_range = [] + start, end = id_range.strip().split("-") + + number_of_digits_in_end = len(make_list(end)) + for multiple in get_factors(number_of_digits_in_end): + bad_ids = get_tokens(int(start), int(end), multiple) + bad_ids_in_range.extend(bad_ids) + + invalid_ids = (list(set(bad_ids_in_range))) + ids_to_sum.extend(invalid_ids) + + final_sum = sum(ids_to_sum) + return final_sum + + +def test_wrap_it_up_part_two_test(): + final_sum = wrap_it_up_part_two(test_ids) + assert final_sum == 4174379265 + +def test_wrap_it_up_part_two_real(): + real_input = open('input_day2.txt').read().split(",") + final_sum = wrap_it_up_part_two(real_input) + print(final_sum) + + + + + + + + + +