Advent of Code 2024 - Day 02 of 25
Table of Contents
Second day of Advent of Code was yesterday 12/02/2024! If you’re here for the first time today, don’t forget to read the post about Day 1!
I classified the second problem as easy (part 1) and medium (part 2).
Tips#
- You need to transform each input line into a list of integers.
- To determine if the list is increasing or decreasing, calculate the difference between the second and first element. The sign of the subtraction result will indicate if the list should be increasing or decreasing. To check if the entire list is increasing or decreasing, continue subtracting elements, two at a time, until the end of the list. When the subtraction value is positive, the list is increasing. If negative, the list is decreasing. But only if the same sign is maintained until the end of the list.
- Remember that since we use L[i+1] - L[i], i must be less than the index of the last element, otherwise you’ll get an error.
Example of an increasing list:
L = [1, 2, 3, 4, 6]
Notice that when we subtract the second from the first element, we get a positive value.
2 - 1 = 1 # L[1] - L[0]
3 - 2 = 1 # L[2] - L[1]
4 - 3 = 1 # L[3] - L[2]
6 - 4 = 2 # L[4] - L[3]
Decreasing:
L = [6, 4, 3, 2, 1]
Notice that when we subtract the second from the first element, we get a negative value.
4 - 6 = -2 # L[1] - L[0]
3 - 4 = -1 # L[2] - L[1]
2 - 3 = -1 # L[3] - L[2]
1 - 2 = -1 # L[4] - L[3]
In day 2’s problem, you have to verify if the sign of the subtraction between list elements is always the same, thus ensuring that the list is increasing or decreasing. Remember that the problem stipulates that the difference between two elements must have the same sign, but the absolute value between two elements cannot be greater than 3.
The abs()
function returns the absolute value of a number, meaning the value without the sign, you can use it when you need to compare a number without considering its sign.
For the second part, one of the solutions is to use combinations (see itertools module, combinations function). Remember that permutations and combinations are different. You can use combinations to remove invalid entries in part 2.
How much Python do you need to know?#
The chapters refer to my book Introduction to Programming with Python.
- Lists - Chapter 6
- Strings - Chapter 7
- Functions, list comprehensions and generators - Chapter 8
- Python’s itertools module
Answer#
You can find the auxiliares.arquivos module listing in Day 1.
from itertools import combinations
from aux import signal
from aux.files import one_list_per_line
MAX_DIFFERENCE = 3
def validate_increasing(lst: list[int]) -> bool:
return all(
signal(d := lst[i + 1] - lst[i]) == 1 and 0 < abs(d) <= MAX_DIFFERENCE
for i in range(len(lst) - 1)
)
def validate_decreasing(lst: list[int]) -> bool:
return all(
signal(d := lst[i + 1] - lst[i]) == -1 and 0 < abs(d) <= MAX_DIFFERENCE
for i in range(len(lst) - 1)
)
def validate_list(lst: list[int]) -> bool:
s = signal(lst[1] - lst[0])
return (
validate_increasing(lst)
if s == 1
else validate_decreasing(lst) if s == -1 else False
)
def validate_report(lists) -> list[bool]:
return [validate_list(lst) for lst in lists]
def validate_with_error(lst):
size = len(lst)
for positions in combinations(range(size), size - 1):
if validate_list([lst[p] for p in positions]):
return True
return False
def validate_report_with_error(lists):
return [validate_with_error(lst) for lst in lists]
test_result = validate_report(one_list_per_line("02/input_test.txt"))
assert test_result.count(True) == 2
print(test_result)
result = validate_report(one_list_per_line("02/input.txt"))
print(result.count(True))
assert result.count(True) == 591
test_result_2 = validate_report_with_error(one_list_per_line("02/input_test.txt"))
print(test_result_2)
assert test_result_2.count(True) == 4
result_2 = validate_report_with_error(one_list_per_line("02/input.txt"))
print(result_2.count(True))
assert result_2.count(True) == 621
aux.signal#
def signal(x: int) -> int:
return 1 if x > 0 else -1 if x < 0 else 0