Skip navigation

The Moderna booster level drained me all day on Dec 1 and did what jab two did during the overnight period (achy enough to wake me up and not get back to slumber easily). To try to wear myself down, I decided to practice a bit of R with the 2021 Advent of Code. There are plenty of superb R bloggers chronicling their daily katas that I do not feel compelled to post every one (truth be told, work and fam tasks/priorities will make devoting any time to this year’s daily puzzles a rare event).

Day 01 was very straightforward (even part 2 which I used {RcppRoll} despite hoping to stick to only base R 4.x) so it’s kinda not worth a post (for me), but Day 02 was kinda fun as I don’t have regular opportunities to use scan() and get().

The input is a series of submarine commands:

forward 5
down 5
forward 8
up 3
down 8
forward 2

with a set of rules that change between parts 1 and 2.

We can read in those commands with scan() which lets us specify a pattern for each line (scan() takes care of dealing with whitespace for you):

scan(
  text = "forward 5
down 5
forward 8
up 3
down 8
forward 2",
what = list(character(0), integer(0))
) |>
  setNames(c("command", "value")) -> input

str(input)
## List of 2
##  $ command: chr [1:6] "forward" "down" "forward" "up" ...
##  $ value  : int [1:6] 5 5 8 3 8 2

The rules (link above) were pretty basic, increment/decrement some variables based on the command input, but I wanted to avoid a bunch of if statements. Since R has the get() function that enables searching by name for an object, we can make a series of functions that have the command as the identifier and then use get() to call the function:

up <- \(x) depth <<- depth - x
down <- \(x) depth <<- depth + x
forward <- \(x) position <<- position + x

position <- depth <- 0

for (idx in seq_along(input$command)) {
  get(input$command[idx], mode = "function")(input$value[idx])
}

(the final answer is computed by position X depth).

While I find this to be a “fun” solution, I’d strongly suggest:

  • avoiding using the new shortcut function declaration in mixed R version shops as it’s very new and likely to be confusing to new R users
  • being wary of the <<- assignment operator as it’s introducing a side-effect (parent/global environment modification) which will come back to bite you in other projects some day
  • ditching the $ referencing in favour of [[]] / [] to avoid partial name matching “gotchas”, and
  • adding explicit documentation to what you’re doing with get() calls (provided you really have a good case for using get() to begin with)

The code only changes slightly for part 2, so I’ll refrain from adding even more unreadable code from this post.

2 Comments

    • Martin Møller Skarbiniks Pedersen
    • Posted 2021-12-02 at 05:59
    • Permalink
    • Reply

    You can solve 2021-day1 easy with tidyverse::lead()
    eg. for part 2:
    leads <- numbers + tidyverse::lead(numbers, n = 1) + tidyverse::lead(numbers, n = 2)
    leads <- leads[!is.na(leads)]
    result 0)
    cat(“2021-day01-part2:”, result, “\n”)

    • Or I can use base R and one package with much, much lighter dependencies :-)

      sum(
        diff(
          RcppRoll::roll_sum(
            scan(
              file = "~/Data/2021-advent-of-code/01-01.txt", 
              what = integer(0)
            ),
            n = 3
          ),
        ) > 0
      ) 
      

4 Trackbacks/Pingbacks

  1. […] by data_admin [This article was first published on R – rud.is, and kindly contributed to R-bloggers]. (You can report issue about the content on this page […]

  2. […] *** This can be a Safety Bloggers Community syndicated weblog from rud.is authored by hrbrmstr. Learn the unique submit at: https://rud.is/b/2021/12/02/2021-advent-of-code-day-02-dont-try-this-at-home-edition/ […]

  3. […] article was first published on R – rud.is, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here) […]

  4. […] 2021 Advent of Code Day 02 “Don’t Try This At Home” Edition […]

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.