2021-02: Dive!

library(data.table)
library(tidyr)

Part 1

dt <- data.table(read.table("input.txt", sep = "\n"))
dt <- separate(dt, "V1", c("d", "n"), sep = " ", convert = TRUE)
dt$n <- ifelse(dt$d == "down", dt$n * -1, dt$n)

abs(dt[d == "forward", .(sum = sum(n))] * 
  as.numeric(dt[d != "forward", .(sum = sum(n))]))
       sum
1: 1635930

Part 2

dt <- data.table(read.table("input.txt", sep = "\n"))
dt <- separate(dt, "V1", c("d", "n"), sep = " ", convert = TRUE)

dt$aim <- ifelse(dt$d == "up" & dt$d != "forward", dt$n * -1, dt$n)
dt$aim <- ifelse(dt$d == "forward", 0, dt$aim)
dt$aim <- cumsum(dt$aim)

dt$h <- ifelse(dt$d == "forward", dt$n, 0)
dt$depth <- ifelse(dt$d == "forward", dt$aim * dt$n, 0)

sum(dt$h, na.rm = TRUE) * sum(dt$depth, na.rm = TRUE)
[1] 1781819478

Speed Edition

Base R once again beats out data.table by just a little bit. The big difference here was moving from colSums to sum, although readLines instead of fread does play a part.

Fastest solution

dtM <- data.frame("V1" = readLines("input.txt"))
dtM <- tidyr::separate(dtM, "V1", c("d", "n"), sep = " ", convert = TRUE)

# part 1
dt <- dtM
dt$n <- ifelse(dt$d == "down", dt$n * -1, dt$n)
abs(sum(dt$n[dt$d == "forward"]) * sum(dt$n[dt$d != "forward"]))
[1] 1635930
# part 2
dt <- dtM
dt$aim <- cumsum(ifelse(dt$d == "up", dt$n * -1, 
                        ifelse(dt$d == "forward", 0, dt$n)))
sum(ifelse(dt$d == "forward", dt$n, 0), na.rm = TRUE) *
  sum(ifelse(dt$d == "forward", dt$aim * dt$n, 0), na.rm = TRUE)
[1] 1781819478

Benchmarks

rbenchmark::benchmark(
  "First try" = {
    library(data.table)
    # part 1
    dt <- data.table(read.table("input.txt", sep = "\n"))
    dt <- tidyr::separate(dt, "V1", c("d", "n"), sep = " ", convert = TRUE)
    dt$n <- ifelse(dt$d == "down", dt$n * -1, dt$n)

    abs(dt[d == "forward", .(sum = sum(n))] * 
          as.numeric(dt[d != "forward", .(sum = sum(n))]))
    
    # part 2
    dt <- data.table(read.table("input.txt", sep = "\n"))
    dt <- tidyr::separate(dt, "V1", c("d", "n"), sep = " ", convert = TRUE)

    dt$aim <- ifelse(dt$d == "up" & dt$d != "forward", dt$n * -1, dt$n)
    dt$aim <- ifelse(dt$d == "forward", 0, dt$aim)
    dt$aim <- cumsum(dt$aim)

    dt$h <- ifelse(dt$d == "forward", dt$n, 0)
    dt$depth <- ifelse(dt$d == "forward", dt$aim * dt$n, 0)
    
    sum(dt$h, na.rm = TRUE) * sum(dt$depth, na.rm = TRUE)
    },
  "Base R" = {
    dtM <- data.frame("V1" = readLines("input.txt"))
    dtM$n <- na.omit(as.numeric(unlist(strsplit(dtM$V1, " "))))
    dtM$d <- as.character(unlist(strsplit(dtM$V1, " ")))[
      is.na(as.numeric(unlist(strsplit(dtM$V1, " "))))]
    
    # part 1
    dt <- dtM
    dt$n <- ifelse(dt$d == "down", dt$n * -1, dt$n)
    abs(sum(dt$n[dt$d == "forward"]) * sum(dt$n[dt$d != "forward"]))
    
    # part 2
    dt <- dtM
    dt$aim <- cumsum(ifelse(dt$d == "up", dt$n * -1, 
                            ifelse(dt$d == "forward", 0, dt$n)))
    sum(ifelse(dt$d == "forward", dt$n, 0), na.rm = TRUE) * 
      sum(ifelse(dt$d == "forward", dt$aim * dt$n, 0), na.rm = TRUE)
    },
  "data.table" = {
    library(data.table)
    dtM <- fread("input.txt", sep = "\n", header = FALSE)
    dtM <- tidyr::separate(dtM, "V1", c("d", "n"), sep = " ", convert = TRUE)

    # part 1
    dt <- dtM
    dt$n <- ifelse(dt$d == "down", dt$n * -1, dt$n)
    abs(colSums(dt[d == "forward", .(n)]) * colSums(dt[d != "forward", .(n)]))
    
    # part 2
    dt <- dtM
    dt$aim <- cumsum(ifelse(dt$d == "up", dt$n * -1, 
                            ifelse(dt$d == "forward", 0, dt$n)))
    sum(ifelse(dt$d == "forward", dt$n, 0), na.rm = TRUE) * 
      sum(ifelse(dt$d == "forward", dt$aim * dt$n, 0), na.rm = TRUE)
    },
  replications = 100, columns = c(1:5), order = "user.self")
        test replications user.self sys.self elapsed
2     Base R          100     0.228    0.007   0.234
3 data.table          100     0.829    0.056   0.885
1  First try          100     1.588    0.117   1.706