Last updated: 2017-11-27

Code version: ef93c91

Session information

sessionInfo()
R version 3.4.2 (2017-09-28)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Sierra 10.12.6

Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRlapack.dylib

locale:
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] bindrcpp_0.2    dplyr_0.7.4     purrr_0.2.2.2   readr_1.1.1     tidyr_0.6.3     tibble_1.3.4    ggplot2_2.2.1   tidyverse_1.1.1

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.13     cellranger_1.1.0 compiler_3.4.2   git2r_0.19.0     plyr_1.8.4       bindr_0.1        forcats_0.2.0    base64enc_0.1-3 
 [9] tools_3.4.2      digest_0.6.12    lubridate_1.6.0  jsonlite_1.5     evaluate_0.10.1  nlme_3.1-131     gtable_0.2.0     lattice_0.20-35 
[17] pkgconfig_2.0.1  rlang_0.1.4      psych_1.7.5      yaml_2.1.14      parallel_3.4.2   haven_1.1.0      xml2_1.1.1       httr_1.3.1      
[25] stringr_1.2.0    knitr_1.17       hms_0.3          rprojroot_1.2    grid_3.4.2       glue_1.2.0       R6_2.2.2         readxl_1.0.0    
[33] foreign_0.8-69   rmarkdown_1.8    modelr_0.1.0     reshape2_1.4.2   magrittr_1.5     backports_1.1.0  scales_0.5.0     htmltools_0.3.6 
[41] rvest_0.3.2      rsconnect_0.8.5  assertthat_0.2.0 mnormt_1.5-5     colorspace_1.3-2 stringi_1.1.5    lazyeval_0.2.0   munsell_0.4.3   
[49] broom_0.4.2     
library(tidyverse)

Load instructions

Load string of step instructions and split into directions (step_dirs) and number of steps (step_dists)

steps <- readLines("../inputs/dir_input.txt") %>% strsplit(", ") %>% unlist()
# Test
#steps <- c("R8", "R4", "R4", "R8")
steps
  [1] "L4"   "L3"   "R1"   "L4"   "R2"   "R2"   "L1"   "L2"   "R1"   "R1"   "L3"   "R5"   "L2"   "R5"   "L4"   "L3"   "R2"   "R2"   "L5"  
 [20] "L1"   "R4"   "L1"   "R3"   "L3"   "R5"   "R2"   "L5"   "R2"   "R1"   "R1"   "L5"   "R1"   "L3"   "L2"   "L5"   "R4"   "R4"   "L2"  
 [39] "L1"   "L1"   "R1"   "R1"   "L185" "R4"   "L1"   "L1"   "R5"   "R1"   "L1"   "L3"   "L2"   "L1"   "R2"   "R2"   "R2"   "L1"   "L1"  
 [58] "R4"   "R5"   "R53"  "L1"   "R1"   "R78"  "R3"   "R4"   "L1"   "R5"   "L1"   "L4"   "R3"   "R3"   "L3"   "L3"   "R191" "R4"   "R1"  
 [77] "L4"   "L1"   "R3"   "L1"   "L2"   "R3"   "R2"   "R4"   "R5"   "R5"   "L3"   "L5"   "R2"   "R3"   "L1"   "L1"   "L3"   "R1"   "R4"  
 [96] "R1"   "R3"   "R4"   "R4"   "R4"   "R5"   "R2"   "L5"   "R1"   "R2"   "R5"   "L3"   "L4"   "R1"   "L5"   "R1"   "L4"   "L3"   "R5"  
[115] "R5"   "L3"   "L4"   "L4"   "R2"   "R2"   "L5"   "R3"   "R1"   "R2"   "R5"   "L5"   "L3"   "R4"   "L5"   "R5"   "L3"   "R1"   "L1"  
[134] "R4"   "R4"   "L3"   "R2"   "R5"   "R1"   "R2"   "L1"   "R4"   "R1"   "L3"   "L3"   "L5"   "R2"   "R5"   "L1"   "L4"   "R3"   "R3"  
[153] "L3"   "R2"   "L5"   "R1"   "R3"   "L3"   "R2"   "L1"   "R4"   "R3"   "L4"   "R5"   "L2"   "L2"   "R5"   "R1"   "R2"   "L4"   "L4"  
[172] "L5"   "R3"   "L4"  
steps_dirs <- gsub("[0-9]", "", steps)
steps_dists <- gsub("[A-Z]", "", steps) %>% as.numeric()

Set up table to recode L & R to compass directions (N, S, E, W)

dirs_lat <- c("N", "S")
dirs_lon <- c("E", "W")
dirs <- data.frame(facing = c("N", "S", "E", "W"), R = c(dirs_lon, rev(dirs_lat)), L = c(rev(dirs_lon), dirs_lat), stringsAsFactors = F)

Recode

facing <- "N"
compass_dirs <- NULL
for(step_dir in steps_dirs){
   compass_dirs <- c(compass_dirs, dirs[dirs$facing == facing, step_dir])
   facing <- tail(compass_dirs, 1)
}

Calculate overall distance in each direction and sum

tibble(compass_dirs, steps_dists) %>% group_by(compass_dirs) %>% summarise(sum = sum(steps_dists)) %>% mutate(orient = case_when(
    compass_dirs %in% dirs_lat ~ "lat",
    TRUE ~ "lon")) %>% 
    group_by(orient) %>% summarise(diff = diff(sum)) %>% pull(diff) %>% sum
[1] 332

Success!

— Part Two —

steps.tbl <- tibble(compass_dirs, steps_dists, steps_dirs) %>% mutate(
    steps_dists_sign = case_when(
        compass_dirs %in% c(dirs_lat[1], dirs_lon[1]) ~ steps_dists,
        TRUE ~ -steps_dists),
    orient = case_when(
        compass_dirs %in% dirs_lat ~ "lat",
        TRUE ~ "lon"))
steps.tbl

Retrace individual steps through coordinate space

trace_steps <- function(last_step, steps = steps.tbl$steps_dists_sign[i], on.axis = TRUE) {
    switch(as.character(on.axis),
           "TRUE" = last_step + sign(steps):steps,
           "FALSE" = rep(last_step, abs(steps)))
}
loc <- list(lon = 0, lat = 0)
for(i in 1:nrow(steps.tbl)){
    axis <- steps.tbl$orient[i] 
    switch(axis,
           "lat" = {
               loc$lat <- c(loc$lat, trace_steps(last_step = tail(loc$lat,1), on.axis = TRUE))
               loc$lon <- c(loc$lon, trace_steps(last_step = tail(loc$lon,1), on.axis = FALSE))},
           "lon" = {
               loc$lon <- c(loc$lon, trace_steps(last_step = tail(loc$lon,1), on.axis = TRUE))
               loc$lat <- c(loc$lat, trace_steps(last_step = tail(loc$lat,1), on.axis = FALSE))}
    )
}
loc <- loc %>% as.tibble()
loc

Find first duplicate location and calculate distance

first_dup <- loc %>% duplicated() %>% which() %>% min
loc %>% slice(first_dup) %>% map_df(abs) %>% rowSums()
[1] 166

Success!

Phew…that took ages… 20.06 and I’m still at work. Time to go home!

LS0tCnRpdGxlOiAiLS0tIERheSAxOiBObyBUaW1lIGZvciBhIFRheGljYWIgLS0tIgphdXRob3I6ICJhbm5ha3J5c3RhbGxpIgpkYXRlOiAyMDE3LTExLTI3Cm91dHB1dDogaHRtbF9ub3RlYm9vawplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQotLS0KCmBgYHtyIGtuaXRyLW9wdHMtY2h1bmssIGluY2x1ZGU9RkFMU0V9CiMgVXBkYXRlIGtuaXRyIGNodW5rIG9wdGlvbnMKIyBodHRwczovL3lpaHVpLm5hbWUva25pdHIvb3B0aW9ucy8jY2h1bmstb3B0aW9ucwprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgY29tbWVudCA9IE5BLAogIGZpZy5hbGlnbiA9ICJjZW50ZXIiLAogIHRpZHkgPSBGQUxTRSwKICBmaWcucGF0aCA9IHBhc3RlMCgiZmlndXJlLyIsIGtuaXRyOjpjdXJyZW50X2lucHV0KCksICIvIikKKQpgYGAKCmBgYHtyIGxhc3QtdXBkYXRlZCwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9CiMgSW5zZXJ0IHRoZSBkYXRlIHRoZSBmaWxlIHdhcyBsYXN0IHVwZGF0ZWQKY2F0KHNwcmludGYoIioqTGFzdCB1cGRhdGVkOioqICVzIiwgU3lzLkRhdGUoKSkpCmBgYAoKYGBge3IgY29kZS12ZXJzaW9uLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30KIyBJbnNlcnQgdGhlIGNvZGUgdmVyc2lvbiAoR2l0IGNvbW1pdCBTSEExKSBpZiBHaXQgcmVwb3NpdG9yeSBleGlzdHMgYW5kIFIKIyBwYWNrYWdlIGdpdDJyIGlzIGluc3RhbGxlZAppZihyZXF1aXJlTmFtZXNwYWNlKCJnaXQyciIsIHF1aWV0bHkgPSBUUlVFKSkgewogIGlmKGdpdDJyOjppbl9yZXBvc2l0b3J5KCkpIHsKICAgIGNvZGVfdmVyc2lvbiA8LSBzdWJzdHIoZ2l0MnI6OmNvbW1pdHMoKVtbMV1dQHNoYSwgMSwgNykKICB9IGVsc2UgewogICAgY29kZV92ZXJzaW9uIDwtICJVbmF2YWlsYWJsZS4gSW5pdGlhbGl6ZSBHaXQgcmVwb3NpdG9yeSB0byBlbmFibGUuIgogIH0KfSBlbHNlIHsKICBjb2RlX3ZlcnNpb24gPC0gIlVuYXZhaWxhYmxlLiBJbnN0YWxsIGdpdDJyIHBhY2thZ2UgdG8gZW5hYmxlLiIKfQpjYXQoc3ByaW50ZigiKipDb2RlIHZlcnNpb246KiogJXMiLCBjb2RlX3ZlcnNpb24pKQpybShjb2RlX3ZlcnNpb24pCmBgYAoKPCEtLSBBZGQgeW91ciBhbmFseXNpcyBoZXJlIC0tPgoKIyMgU2Vzc2lvbiBpbmZvcm1hdGlvbgoKPCEtLSBJbnNlcnQgdGhlIHNlc3Npb24gaW5mb3JtYXRpb24gaW50byB0aGUgZG9jdW1lbnQgLS0+CmBgYHtyIHNlc3Npb24taW5mb30Kc2Vzc2lvbkluZm8oKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgoKIyMgTG9hZCBpbnN0cnVjdGlvbnMKCkxvYWQgc3RyaW5nIG9mIHN0ZXAgaW5zdHJ1Y3Rpb25zIGFuZCBzcGxpdCBpbnRvIGRpcmVjdGlvbnMgKGBzdGVwX2RpcnNgKSBhbmQgbnVtYmVyIG9mIHN0ZXBzIChgc3RlcF9kaXN0c2ApCgpgYGB7cn0Kc3RlcHMgPC0gcmVhZExpbmVzKCIuLi9pbnB1dHMvZGlyX2lucHV0LnR4dCIpICU+JSBzdHJzcGxpdCgiLCAiKSAlPiUgdW5saXN0KCkKIyBUZXN0CiNzdGVwcyA8LSBjKCJSOCIsICJSNCIsICJSNCIsICJSOCIpCgpzdGVwcwpgYGAKCmBgYHtyfQpzdGVwc19kaXJzIDwtIGdzdWIoIlswLTldIiwgIiIsIHN0ZXBzKQpzdGVwc19kaXN0cyA8LSBnc3ViKCJbQS1aXSIsICIiLCBzdGVwcykgJT4lIGFzLm51bWVyaWMoKQpgYGAKCgojIyMgU2V0IHVwIHRhYmxlIHRvIHJlY29kZSBgTGAgJiBgUmAgdG8gY29tcGFzcyBkaXJlY3Rpb25zIChgTmAsIGBTYCwgYEVgLCBgV2ApCgoKCgpgYGB7cn0KZGlyc19sYXQgPC0gYygiTiIsICJTIikKZGlyc19sb24gPC0gYygiRSIsICJXIikKZGlycyA8LSBkYXRhLmZyYW1lKGZhY2luZyA9IGMoIk4iLCAiUyIsICJFIiwgIlciKSwgUiA9IGMoZGlyc19sb24sIHJldihkaXJzX2xhdCkpLCBMID0gYyhyZXYoZGlyc19sb24pLCBkaXJzX2xhdCksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKQpgYGAKCiMjIyBSZWNvZGUgCmBgYHtyfQpmYWNpbmcgPC0gIk4iCmNvbXBhc3NfZGlycyA8LSBOVUxMCmZvcihzdGVwX2RpciBpbiBzdGVwc19kaXJzKXsKICAgY29tcGFzc19kaXJzIDwtIGMoY29tcGFzc19kaXJzLCBkaXJzW2RpcnMkZmFjaW5nID09IGZhY2luZywgc3RlcF9kaXJdKQogICBmYWNpbmcgPC0gdGFpbChjb21wYXNzX2RpcnMsIDEpCn0KYGBgCgojIyBDYWxjdWxhdGUgb3ZlcmFsbCBkaXN0YW5jZSBpbiBlYWNoIGRpcmVjdGlvbiBhbmQgc3VtCgpgYGB7cn0KdGliYmxlKGNvbXBhc3NfZGlycywgc3RlcHNfZGlzdHMpICU+JSBncm91cF9ieShjb21wYXNzX2RpcnMpICU+JSBzdW1tYXJpc2Uoc3VtID0gc3VtKHN0ZXBzX2Rpc3RzKSkgJT4lIG11dGF0ZShvcmllbnQgPSBjYXNlX3doZW4oCiAgICBjb21wYXNzX2RpcnMgJWluJSBkaXJzX2xhdCB+ICJsYXQiLAogICAgVFJVRSB+ICJsb24iKSkgJT4lIAogICAgZ3JvdXBfYnkob3JpZW50KSAlPiUgc3VtbWFyaXNlKGRpZmYgPSBkaWZmKHN1bSkpICU+JSBwdWxsKGRpZmYpICU+JSBzdW0KYGBgCgoKIyMgU3VjY2VzcyEKCiFbXSguLi9zY3JlZW5zaG90cy90ZXN0LURheTFfMS5wbmcpCgojIC0tLSBQYXJ0IFR3byAtLS0KCmBgYHtyfQpzdGVwcy50YmwgPC0gdGliYmxlKGNvbXBhc3NfZGlycywgc3RlcHNfZGlzdHMsIHN0ZXBzX2RpcnMpICU+JSBtdXRhdGUoCiAgICBzdGVwc19kaXN0c19zaWduID0gY2FzZV93aGVuKAogICAgICAgIGNvbXBhc3NfZGlycyAlaW4lIGMoZGlyc19sYXRbMV0sIGRpcnNfbG9uWzFdKSB+IHN0ZXBzX2Rpc3RzLAogICAgICAgIFRSVUUgfiAtc3RlcHNfZGlzdHMpLAogICAgb3JpZW50ID0gY2FzZV93aGVuKAogICAgICAgIGNvbXBhc3NfZGlycyAlaW4lIGRpcnNfbGF0IH4gImxhdCIsCiAgICAgICAgVFJVRSB+ICJsb24iKSkKCnN0ZXBzLnRibApgYGAKCiMjIFJldHJhY2UgaW5kaXZpZHVhbCBzdGVwcyB0aHJvdWdoIGNvb3JkaW5hdGUgc3BhY2UKCmBgYHtyfQp0cmFjZV9zdGVwcyA8LSBmdW5jdGlvbihsYXN0X3N0ZXAsIHN0ZXBzID0gc3RlcHMudGJsJHN0ZXBzX2Rpc3RzX3NpZ25baV0sIG9uLmF4aXMgPSBUUlVFKSB7CiAgICBzd2l0Y2goYXMuY2hhcmFjdGVyKG9uLmF4aXMpLAogICAgICAgICAgICJUUlVFIiA9IGxhc3Rfc3RlcCArIHNpZ24oc3RlcHMpOnN0ZXBzLAogICAgICAgICAgICJGQUxTRSIgPSByZXAobGFzdF9zdGVwLCBhYnMoc3RlcHMpKSkKfQoKCmxvYyA8LSBsaXN0KGxvbiA9IDAsIGxhdCA9IDApCmZvcihpIGluIDE6bnJvdyhzdGVwcy50YmwpKXsKICAgIGF4aXMgPC0gc3RlcHMudGJsJG9yaWVudFtpXSAKICAgIHN3aXRjaChheGlzLAogICAgICAgICAgICJsYXQiID0gewogICAgICAgICAgICAgICBsb2MkbGF0IDwtIGMobG9jJGxhdCwgdHJhY2Vfc3RlcHMobGFzdF9zdGVwID0gdGFpbChsb2MkbGF0LDEpLCBvbi5heGlzID0gVFJVRSkpCiAgICAgICAgICAgICAgIGxvYyRsb24gPC0gYyhsb2MkbG9uLCB0cmFjZV9zdGVwcyhsYXN0X3N0ZXAgPSB0YWlsKGxvYyRsb24sMSksIG9uLmF4aXMgPSBGQUxTRSkpfSwKICAgICAgICAgICAibG9uIiA9IHsKICAgICAgICAgICAgICAgbG9jJGxvbiA8LSBjKGxvYyRsb24sIHRyYWNlX3N0ZXBzKGxhc3Rfc3RlcCA9IHRhaWwobG9jJGxvbiwxKSwgb24uYXhpcyA9IFRSVUUpKQogICAgICAgICAgICAgICBsb2MkbGF0IDwtIGMobG9jJGxhdCwgdHJhY2Vfc3RlcHMobGFzdF9zdGVwID0gdGFpbChsb2MkbGF0LDEpLCBvbi5heGlzID0gRkFMU0UpKX0KICAgICkKfQpsb2MgPC0gbG9jICU+JSBhcy50aWJibGUoKQpsb2MKYGBgCgojIyBGaW5kIGZpcnN0IGR1cGxpY2F0ZSBsb2NhdGlvbiBhbmQgY2FsY3VsYXRlIGRpc3RhbmNlCmBgYHtyfQpmaXJzdF9kdXAgPC0gbG9jICU+JSBkdXBsaWNhdGVkKCkgJT4lIHdoaWNoKCkgJT4lIG1pbgpsb2MgJT4lIHNsaWNlKGZpcnN0X2R1cCkgJT4lIG1hcF9kZihhYnMpICU+JSByb3dTdW1zKCkKYGBgCgoKIyMgU3VjY2VzcyEKClBoZXcuLi50aGF0IHRvb2sgYWdlcy4uLiAyMC4wNiBhbmQgSSdtIHN0aWxsIGF0IHdvcmsuIFRpbWUgdG8gZ28gaG9tZSEKCiFbXSguLi9zY3JlZW5zaG90cy90ZXN0LURheTFfMi5wbmcpCgo=