Advent of code 2024 - Dia 15 de 25

O décimo quinto dia do Advent of Code foi ontem 15/12/2024! Se você caiu aqui hoje pela primeira vez, não deixe de ler os posts sobre o Dia 1, Dia 2, Dia 3, Dia 4, Dia 5, Dia 6, Dia 7, Dia 8, Dia 9, Dia 10, Dia 11, Dia 12, Dia 13 e Dia 14.

Classifiquei o décimo quinto problema como médio (parte 1) e médio (parte 2).

Dicas

  • A primeira parte do problema é ler o labirinto (armazém) e os comandos do robô.
  • Utilize as entradas de exemplo para testar a solução.
  • Você precisa detectar na entrada do labirinto, onde estão as paredes, o robô e as caixas.
  • Os comandos estão em várias linhas, fica mais fácil se você concatená-las em uma só string.
  • Você pode implementar as direções do robô (comandos) usando vetores.
  • Vetores também podem ser utilizados para marcar as posições das caixas e paredes.
  • As paredes circundam todo o armazém, você não precisa de preocupar com o robô saindo do armazém.
  • Para verificar se o robô pode se mexer, verifique se a nova posição está livre. Neste caso, mova o robô, atualizando a posição.
  • Se a posição seguinte for ocupada por uma parede, o robô não pode se mexer e fica no mesmo lugar.
  • Para saber se pode mover as caixas, você pode tentar recursivamente todas as caixas a partir da direção do movimento. A cada caixa, verifique se ela pode se mover (espaço em branco na direção do movimento). Caso uma das caixas não possa ser movida, o movimento é cancelado.
  • Lembre-se que o robô pode empurrar várias caixas ao mesmo tempo. Uma função recursiva pode ajudar a resolver este problema.
  • Na parte 1, as caixas são do mesmo tamanho das paredes, ou seja, cada caixa ocupa uma posição. Na parte 2, cada caixa ocupa duas posições.
  • A parte 2 é um pouco mais complexa, pois você pode mover mais que colunas e linhas de caixas, mas partes inteiras do armazém.
  • O movimento horizontal é semelhante ao da parte 1, pois cada caixa tem altura de apenas um caractere, como na parte 1.
  • Cada movimento na parte 2 pode mover até 2 caixas ao mesmo tempo. Mas esse movimento é feito em cascata, logo estas duas caixas podem mover outras 2, 3, ou mais caixas. Cada movimento de caixa pode movimentar a cada passo, zero, uma ou duas caixas, mas pode ocasionar o movimento de muitas outras.
  • Na parte 2, você precisa verificar se o movimento inteiro é válido. Por exemplo, quando as caixas sendo empurradas formam um V ou ficam presas em uma parede, todas tem que parar de se mover. Se você implementar a função de movimento como na parte 1, verá que as caixas vão se mexer em vários pedaços, o que leva a resposta errada.

Quanto de Python você precisa saber?

Os capítulos se referem ao meu livro Introdução à Programação com Python.

Ler mais

Advent of code 2024 - Dia 14 de 25

O décimo quarto dia do Advent of Code foi ontem 14/12/2024! Se você caiu aqui hoje pela primeira vez, não deixe de ler os posts sobre o Dia 1, Dia 2, Dia 3, Dia 4, Dia 5, Dia 6, Dia 7, Dia 8, Dia 9, Dia 10, Dia 11, Dia 12 e Dia 13.

Classifiquei o décimo quarto problema como médio (parte 1) e médio (parte 2).

Dicas

  • Mais um problema com labirinto :-D É muito bom ter uma classe como a Labirinto.
  • Este problema também utiliza vetores, a classe Vector2d será bem útil.
  • Você pode utilizar uma expressão regular para extrair os dados da entrada.
  • Organizar o código em classes é uma boa prática. Neste caso, cada robô é claramente um objeto.
  • Lembre da divisão inteira para calcular a coluna e linhas do meio.
  • Cada robô tem uma posição e um vetor velocidade.
  • Quando o robô se move para uma posição fora do labirinto (Zona), ela pode ser corrigida usando o operador módulo (ver capítulo 2, propriedades do resto da divisão).
  • Você pode ver o avanço do tempo como uma simulação.
  • Utilize os valores de teste para verificar se sua solução responde ao problema. Comece por testar a movimentação dos robôs e depois a teleportação que ocorre quando eles se movem fora da Zona.
  • A Parte 2 é um pouco diferente das demais. Precisamos encontrar um padrão de natal na posição dos robôs.
  • Depois de observar a resposta, avançando a simulação manualmente, pois o enunciado não deixa claro; podemos ver que o segundo da simulação quando os robôs formam a figura de natal é o primeiro em que não há sobreposição de robôs, ou seja, não há dois robôs na mesma posição.

Quanto de Python você precisa saber?

Os capítulos se referem ao meu livro Introdução à Programação com Python.

Ler mais

Advent of code 2024 - Dia 13 de 25

O décimo terceiro dia do Advent of Code foi ontem 13/12/2024! Se você caiu aqui hoje pela primeira vez, não deixe de ler os posts sobre o Dia 1, Dia 2, Dia 3, Dia 4, Dia 5, Dia 6, Dia 7, Dia 8, Dia 9, Dia 10, Dia 11 e Dia 12.

Classifiquei o décimo terceiro problema como médio (parte 1) e médio (parte 2).

Dicas

  • O programa tem um entrada em várias linhas
  • Você pode usar expressões regulares para extrair os valores de cada linha.
  • Cada grupo de 4 linhas, trás 4 valores, a entrada para o programa.
  • Você pode observar o problema como uma sistema de equações lineares.
  • O sistema não tem solução quando a resposta do sistema de equações não é inteira.
  • Ache os valores de a e b que satisfaçam a equação. Neste caso, calcule o custo como sendo 3*a + b.
  • Se você utilizar um otimizador como scipy.optimize.linprog ou Pulp você poderá ter problemas com os grandes números da parte 2.
  • Modelo no Pulp:
def psolve(ax, ay, bx, by, rx, ry):

    model = LpProblem("Minimize Tokens", LpMinimize)
    A = LpVariable("A", lowBound=0, cat=LpInteger)
    B = LpVariable("B", lowBound=0, cat=LpInteger)

    model += 3 * A + B
    model += ax * A + bx * B == rx
    model += ay * A + by * B == ry
    model.solve()    

    return model, value(A), value(B)
  • Com scipy:
from scipy.optimize import linprog

def minimize_cost(x, y, r, c, max_tokens=100):    
    A_eq = [x, y]  # Coefficient matrix for equality constraints
    b_eq = r  # Right-hand side of the equations
    
    result = linprog(
        c,
        A_eq=A_eq,
        b_eq=b_eq,
        method="highs",
        bounds=[(0, max_tokens), (0, max_tokens)],
        integrality=[1, 1],
    )

    # Check if the optimization was successful
    if result.success:
        a, b = result.x
        print(
            f"The optimized solution is: a = {a}, b = {b}, with a cost of {3*a + b} {result.fun}"
        )
        return a, b, 3 * a + b

    else:
        print("No valid solution (could not optimize).", result)
        return None

Quanto de Python você precisa saber?

Os capítulos se referem ao meu livro Introdução à Programação com Python.

Ler mais

Advent of code 2024 - Dia 12 de 25

O décimo segundo dia do Advent of Code foi ontem 12/12/2024! Se você caiu aqui hoje pela primeira vez, não deixe de ler os posts sobre o Dia 1, Dia 2, Dia 3, Dia 4, Dia 5, Dia 6, Dia 7, Dia 8, Dia 9, Dia 10 e Dia 11.

Classifiquei o décimo segundo problema como fácil (parte 1) e médio (parte 2).

Dicas

  • Outro problema com labirintos ou mapas de caracteres.
  • Você pode construir uma zona, procurando por elementos idênticos nas posições acima, abaixo, a esquerda e a direita do nó corrente.
  • Tente visualizar o mapa de caracteres como uma matriz. Agora imagine cada elemento como um nó de um grafo, conectado aos seus vizinhos.
  • Lembre-se de marcar os nós já visitados
  • Você pode construir uma cerca sempre que o elemento na direção sendo explorada for diferente do elemento atual.
  • Na parte 1, a área é igual a quantidade de elementos na mesma zona. Para calcular o perímetro, você precisa saber quantas barreiras colocou em cada posição.
  • A parte 2 traz uma forma diferente de calcular o preço, mas o problema é bem parecido com a parte 1. Agora, você precisa olhar todas as barreiras da zona e verificar quantas são linhas e colunas contíguas.
  • Você pode organizar as linhas pela coordenada y de suas cercas. Linhas contíguas terão o mesmo valor na coordenada y. Se ordenadas adequadamente, o segmento seguinte será o próximo com uma posição em x apenas 1 elemento maior que a anterior. Desta forma, você consegue contar as linhas contíguas.
  • As colunas seguem o mesmo princípio, mas agora você precisa ordenar as cercas pela coordenada x. Da mesma forma, uma coluna é contígua se o próximo segmento está na linha seguinte.
  • É mais fácil organizar os dados se as cercas horizontais e verticais estiverem separadas.

Quanto de Python você precisa saber?

Os capítulos se referem ao meu livro Introdução à Programação com Python.

Ler mais

Advent of code 2024 - Dia 11 de 25

O décimo primeiro dia do Advent of Code foi ontem 11/12/2024! Se você caiu aqui hoje pela primeira vez, não deixe de ler os posts sobre o Dia 1, Dia 2, Dia 3, Dia 4, Dia 5, Dia 6, Dia 7, Dia 8, Dia 9 e Dia 10.

Classifiquei o décimo primeiro problema como fácil (parte 1) e médio (parte 2).

Dicas

  • Tanto a parte 1 quanto a parte 2 usam as mesmas regras para gerar as pedras.
  • Uma pedra 0 vira uma pedra 1
  • Uma pedra com número par de dígitos vira duas pedras
  • Se não entrar em nenhuma dessas condições, o valor da pedra é multiplicado por 2024.
  • A geração das pedras na parte 1 é bem interessante e fácil de implementar.
  • O problema traz vários valores de testes que você deve utilizar para validar suas funções
  • Você pode usar qualquer uma das respostas para a parte 1.
  • A parte 2 é complexa porque não há espaço suficiente para guardar tantas pedras. São centenas de trilhões de pedras, guardar cada uma em um elemento da lista não é interessante.
  • Na parte 2, lembre que o objetivo é calcular o número de pedras, não o valor das pedras em si.
  • Quando a pedra tem um número par de dígitos, ela gera duas pedras. Todos os outros valores geram apenas uma pedra. Se você considerar esta propriedade, você pode incrementar o contador de pedras sem guardar todas as pedras.

Quanto de Python você precisa saber?

Os capítulos se referem ao meu livro Introdução à Programação com Python.

Ler mais

Advent of code 2024 - Dia 10 de 25

O décimo dia do Advent of Code foi ontem 10/12/2024! Se você caiu aqui hoje pela primeira vez, não deixe de ler os posts sobre o Dia 1, Dia 2, Dia 3, Dia 4, Dia 5, Dia 6, Dia 7, Dia 8 e Dia 9.

Classifiquei o décimo problema como fácil (parte 1) e fácil (parte 2). O problema é bem parecido com o dia 4.

Dicas

  • Você pode começar a procurar os caminhos quando encontrar o ‘0’ no labirinto.

Ler mais

Advent of code 2024 - Dia 09 de 25

O nono dia do Advent of Code foi ontem 09/12/2024! Se você caiu aqui hoje pela primeira vez, não deixe de ler os posts sobre o Dia 1, Dia 2, Dia 3, Dia 4, Dia 5, Dia 6, Dia 7 e Dia 8.

Classifiquei o nono problema como fácil (parte 1) e médio (parte 2).

Dicas

  • Lembre-se que strings em Python são imutáveis

  • Se você precisa alterar os caracteres de uma string, você pode transformá-la em uma lista de caracteres e reconvertê-la quando terminar.

Ler mais

Advent of code 2024 - Dia 08 de 25

O oitavo dia do Advent of Code foi ontem 08/12/2024! Se você caiu aqui hoje pela primeira vez, não deixe de ler os posts sobre o Dia 1, Dia 2, Dia 3, Dia 4, Dia 5, Dia 6 e Dia 7.

Classifiquei o oitavo problema como fácil (parte 1) e fácil (parte 2).

Dicas

  • O problema também utiliza uma espécie de labirinto para representar o mapa.

  • Se você considerar cada par de antenas como pontos, pode imaginar uma linha que passa entre eles.

Ler mais

Advent of code 2024 - Dia 07 de 25

O sétimo dia do Advent of Code foi ontem 07/12/2024! Se você caiu aqui hoje pela primeira vez, não deixe de ler os posts sobre o Dia 1, Dia 2, Dia 3, Dia 4, Dia 5 e Dia 6.

Classifiquei o sétimo problema como fácil (parte 1) e fácil (parte 2).

Dicas

  • A parte 1 consiste em aplicar uma lista de operações sobre uma lista de operandos.

  • Você vai ter mais operandos que operadores.

  • Você pode usar iter e next para combinar listas de tamanhos diferentes.

Ler mais

Advent of code 2024 - Dia 06 de 25

O sexto dia do Advent of Code foi ontem 06/12/2024! Se você caiu aqui hoje pela primeira vez, não deixe de ler os posts sobre o Dia 1, Dia 2, Dia 3, Dia 4, e Dia 5.

Classifiquei o sexto problema como médio (parte 1) e difícil (parte 2).

Dicas

  • Novamente, um problema com labirinto, onde cada caractere pode ser visto como um elemento em uma matriz.

  • Como você vai precisar constantemente verificar os limites do labirinto, posições válidas e obstáculos, recomendo criar uma classe para representar o labirinto.

Ler mais