O Advent of Code é um Calendário do Advento desenvolvido por Eric Wastl composto por 25 pequenos exercícios de programação que vão sendo disponibilizados, um a um, entre 1º de dezembro e o Natal de cada ano.
Meu objetivo com o Advent of R é resolver todos os problemas do Advent of Code 2021 em R e documentar o processo através desta série de posts. Todo dia entre 01/12/2021 e 25/12/2021 eu vou tentar resolver o novo problema, documentar a minha solução aqui no blog e subir os meus scripts completos para um repositório público no GitHub.
A minha esperança é que, com essa série, mais pessoas pratiquem seus conhecimentos de R resolvendo exercícios divertidos e desafiadores! Ao final da jornada vamos todos ter afiado nossas habilidades de R e, quem sabe, divulgado essa linguagem incrível para mais pessoas. Boas festas e bom código!
Mergulhe (A)
A parte 1 do segundo dia do AoC pede para
lermos uma lista de comandos para um submarino e calcular a sua posição final.
Os comandos possíveis são forward X
(soma X à posição horizontal), up X
(subtrai X da profundidade) e down X
(soma X à profundidade), então precisamos
fazer um dplyr::group_by(command == "forward")
para que um grupo represente
a posição horizontal e um represente a profundidade.
Para concluir o código, como a resposta final é a posição horizontal
multiplicada pela profundidade, temos que fazer um prod()
ao final:
"data-raw/02a_dive.txt" |>
readr::read_delim(" ", col_names = c("command", "x")) |>
dplyr::mutate(x = ifelse(command == "up", -x, x)) |>
dplyr::group_by(command == "forward") |>
dplyr::summarise(x = sum(x)) |>
dplyr::summarise(x = prod(x)) |>
dplyr::pull(x)
#> [1] 1727835
Mergulhe (B)
A parte 2 complica um pouco a nossa vida. Os mesmos comandos agora possuem outro significado:
down X
aumenta a mira em X unidadesup X
diminui a mira em X unidades.forward X
faz duas coisas:- Aumenta a posição horizontal em X unidades.
- Aumenta a profundidade em X vezes a mira atual.
O meu código da primeira parte não permitiria resolver isso de forma eficiente.
Minha solução foi fazer uma cumsum()
da posição horizontal e uma da mira, que
são as partes mais simples. Depois eu calculei a profundidade com
cumsum(aim * x)
(dado que a mira tinha sido calculada no passo anterior).
A saída, mais uma vez é o produto entre a posição horizontal e a profundidade.
Dessa vez a resposta vai estar na última linha da tabela, então o código precisa
de um tail(1)
.
"data-raw/02a_dive.txt" |>
readr::read_delim(" ", col_names = c("command", "x")) |>
dplyr::mutate(
horizontal = ifelse(command == "forward", x, 0),
horizontal = cumsum(horizontal),
aim = ifelse(command == "down", x, 0),
aim = ifelse(command == "up", -x, aim),
aim = cumsum(aim),
depth = ifelse(command == "forward", aim * x, 0),
depth = cumsum(depth),
output = horizontal * depth
) |>
utils::tail(1) |>
dplyr::pull(output)
#> [1] 1544000595