Advent of code 2024 - Dia 02 de 25
Conteúdo
Segundo dia do Advent of Code foi ontem 02/12/2024! Se você caiu aqui hoje pela primeira vez, não deixe de ler o post sobre o Dia 1!
Classifiquei o segundo problema como fácil (parte 1) e médio (parte 2).
Dicas#
- Você precisa transformar cada linha de entrada em uma lista de inteiros.
- Para saber se a lista é crescente ou decrescente, calcule a diferença entre o segundo e o primeiro elemento. O sinal do resultado da subtração indicará se a lista é deve ser crescente ou decrescente. Para saber se a lista inteira é crescente ou decrescente, continue subtraindo os elementos, dois a dois, até o final da lista. Quando a valor da subtração for positivo, a lista é crescente. Se negativo, a lista é decrescente. Mas somente se o mesmo sinal for mantido até o final da lista.
- Lembre-se que como usamos L[i+1] - L[i], i deve ser menor que o índice do último elemento, caso contrário você terá um erro.
Exemplo de lista crescente:
L = [1, 2, 3, 4, 6]
Veja que ao subtrairmos o segundo pelo primeiro elemento, temos um valor positivo.
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]
Decrescente:
L = [6, 4, 3, 2, 1]
Veja que ao subtrairmos o segundo pelo primeiro elemento, temos um valor negativo.
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]
No problema do dia 2, você tem que verificar se o sinal da subtração entre os elementos da lista é sempre o mesmo, desta forma garantindo que a lista é crescente ou decrescente. Lembre que o problema estipula que a diferença entre dois elementos deve ter o mesmo sinal, mas que o valor absoluto entre dois elementos não pode ser maior que 3.
A função abs()
retorna o valor absoluto de um número, ou seja, o valor sem o sinal, você pode utilizá-la quando precisar comparar um número sem considerar o sinal.
Para a segunda parte, uma das soluções é usar combinações (ver módulo itertools, função combinations). Lembre-se que permutações e combinação são diferentes. Você pode utilizar combinações para remover as entradas inválidas na parte 2.
Quanto de Python você precisa saber?#
Os capítulos se referem ao meu livro Introdução à Programação com Python.
- Listas - Capítulo 6
- Strings - Capítulo 7
- Funções, list comprehensions e geradores - Capítulo 8
- Módulo itertools do python
Resposta#
A listagem do módulo auxiliares.arquivos você encontra no Dia 1.
from itertools import combinations
from auxiliares import signal
from auxiliares.arquivos import uma_lista_por_linha
DIFERENÇA_MÁXIMA = 3
def valida_crescente(lista: list[int]) -> bool:
return all(
signal(d := lista[i + 1] - lista[i]) == 1 and 0 < abs(d) <= DIFERENÇA_MÁXIMA
for i in range(len(lista) - 1)
)
def valida_decrescente(lista: list[int]) -> bool:
return all(
signal(d := lista[i + 1] - lista[i]) == -1 and 0 < abs(d) <= DIFERENÇA_MÁXIMA
for i in range(len(lista) - 1)
)
def valida_lista(lista: list[int]) -> bool:
s = signal(lista[1] - lista[0])
return (
valida_crescente(lista)
if s == 1
else valida_decrescente(lista) if s == -1 else False
)
def valida_relatório(listas) -> list[bool]:
return [valida_lista(lista) for lista in listas]
def valida_com_erro(lista):
t = len(lista)
for posições in combinations(range(t), t - 1):
if valida_lista([lista[p] for p in posições]):
return True
return False
def valida_relatório_com_erro(listas):
return [valida_com_erro(lista) for lista in listas]
resultado_teste = valida_relatório(uma_lista_por_linha("02/input_test.txt"))
assert resultado_teste.count(True) == 2
print(resultado_teste)
resultado = valida_relatório(uma_lista_por_linha("02/input.txt"))
print(resultado.count(True))
assert resultado.count(True) == 591
resultado_testes_2 = valida_relatório_com_erro(uma_lista_por_linha("02/input_test.txt"))
print(resultado_testes_2)
assert resultado_testes_2.count(True) == 4
resultado_2 = valida_relatório_com_erro(uma_lista_por_linha("02/input.txt"))
print(resultado_2.count(True))
assert resultado_2.count(True) == 621
auxiliares.signal#
def signal(x: int) -> int:
return 1 if x > 0 else -1 if x < 0 else 0