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!
Aventura Hidrotermal (A)
O quinto dia do AoC foi um pouco mais tranquilo do que o anterior porque eu tive ajuda da incrível Renata Hirota. Hoje tínhamos as coordenadas cartesianas do início e do fim de tubulações submarinas e o objetivo era descobrir quantos pontos do plano tinham mais de uma tubulação passando por eles. No primeiro item deveríamos considerar apenas as tubulações verticais e horizontais.
Uma entrada do tipo
1,1 -> 1,3
cobria os pontos1,1
,1,2
e1,3
.Uma entrada do tipo
9,7 -> 7,7
cobria os pontos9,7
,8,7
e7,7
.
A minha ideia começava filtrando os pontos em que x1 == x2
ou y1 == y2
e
expandindo as coordenadas para criar uma lista que contivesse todos os pontos
pelos quais as tubulações passavam. Eu resolvi isso com o paste(x1:x2, y1:y2)
,
pois a paste()
repetiria a coordenada que não muda ao longo da coordenada que
muda: paste(9:7, 7:7) := "9 7" "8 7" "7 7"
.
Depois disso bastava contar o números de ocorrências de cada ponto do plano, filtrar aqueles que ocorriam mais de 1 vez e contar quantos pontos restavam. Esta era a saída do problema.
"data-raw/05a_hydrothermal_venture.txt" |>
readr::read_csv(col_names = c("x1", "y1x2", "y2")) |>
tidyr::separate(sep = " -> ", col = "y1x2", into = c("y1", "x2")) |>
dplyr::filter(x1 == x2 | y1 == y2) |>
dplyr::mutate(
dif_x = purrr::map2(x1, x2, seq),
dif_y = purrr::map2(y1, y2, seq),
coord = purrr::map2(dif_x, dif_y, paste)
) |>
tidyr::unnest(coord) |>
dplyr::count(coord) |>
dplyr::filter(n > 1) |>
nrow()
#> [1] 7142
Aventura Hidrotermal (B)
O segundo item parecia bastante mais complexo, pois agora deveríamos considerar
todas as tubulações da entrada, removendo o dplyr::filter()
do item anterior.
Mas uma especificação do enunciado facilitou tudo: todas as linhas diagonais
tinham inclinação de 45 graus.
Uma entrada do tipo
1,1 -> 3,3
cobria os pontos1,1
,2,2
e3,3
.Uma entrada do tipo
9,7 -> 7,9
cobria os pontos9,7
,8,8
e7,9
.
Isso significa que a estratégia do paste()
continuava funcionando! Note que
paste(1:3, 1:3) := "1 1" "2 2" "3 3"
, então bastou tirar o dplyr::filter()
que a solução estava pronta.
"data-raw/05b_hydrothermal_venture.txt" |>
readr::read_csv(col_names = c("x1", "y1x2", "y2")) |>
tidyr::separate(sep = " -> ", col = "y1x2", into = c("y1", "x2")) |>
dplyr::mutate(
dif_x = purrr::map2(x1, x2, seq),
dif_y = purrr::map2(y1, y2, seq),
coord = purrr::map2(dif_x, dif_y, paste)
) |>
tidyr::unnest(coord) |>
dplyr::count(coord) |>
dplyr::filter(n > 1) |>
nrow()
#> [1] 20012