Advent of R: Dia 05

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 pontos 1,1, 1,2 e 1,3.

  • Uma entrada do tipo 9,7 -> 7,7 cobria os pontos 9,7, 8,7 e 7,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 pontos 1,1, 2,2 e 3,3.

  • Uma entrada do tipo 9,7 -> 7,9 cobria os pontos 9,7, 8,8 e 7,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
comments powered by Disqus