input<-read_lines("Day16Sample1.txt")
### make the maze into a dict, find the start and end
reindeermaze<-dict()
for(i in 1:length(input)){
  x<-unlist(str_split(input[i],""))
  for(j in 1:length(x)){
    switch(x[j],
           "#"=reindeermaze$set(str_flatten(c(i,j),"~"),0),
           "S"=reinstart<-c(i,j),
           "E"=reinend<-c(i,j),
           {})}}

Part 1

Just a very, very straightforward search -

N=0 E=1 S=2 W=3

mazepath<-function(mz,st,en){
  beenthere<-dict()
  pq<-priority_queue()
  ### pushing starting position, direction, & score
  ### pq is the distance to the end + the current score 
  pq$push(c(st,1,0),-sum(abs(st-en)))
  while(pq$size()>0){
    curr<-pq$pop()
    ### if at the end, leave
    if(all(curr[1:2]==en)){return(curr[4])}
    ### if have been there facing that direction, stop
    if(beenthere$has(str_flatten(curr[1:3],"~"))){next}
    beenthere$set(str_flatten(curr[1:3],"~"),0)
    ### turn clockwise & counterclockwise
    pq$push(c(curr[1:2],(curr[3]+1)%%4,curr[4]+1000),-sum(abs(en-curr[1:2]),curr[4]))
    pq$push(c(curr[1:2],(curr[3]-1)%%4,curr[4]+1000),-sum(abs(en-curr[1:2]),curr[4]))
    ### move, depending on which direction currently facing
    nxt<-FALSE
    d<-as.character(curr[3])
    switch(d,
           "0"=if(!mz$has(str_flatten(curr[1:2]+c(-1,0),"~"))){nxt<-curr[1:2]+c(-1,0)},
           "1"=if(!mz$has(str_flatten(curr[1:2]+c(0,1),"~"))){nxt<-curr[1:2]+c(0,1)},
           "2"=if(!mz$has(str_flatten(curr[1:2]+c(1,0),"~"))){nxt<-curr[1:2]+c(1,0)},
           "3"=if(!mz$has(str_flatten(curr[1:2]+c(0,-1),"~"))){nxt<-curr[1:2]+c(0,-1)},
           cat("bad direction\n"))
    if(!any(nxt==FALSE)){
      pq$push(c(nxt,curr[3],curr[4]+1),-sum(abs(en-nxt),curr[4]))}}
  beenthere}
part1<-mazepath(reindeermaze,reinstart,reinend)
part1
[1] 7036

Part 2

Because I need to save the path during the search (and return all paths), I need to make some small changes:

bestseat<-function(mz,st,en){
  beenthere<-dict()
  pq<-priority_queue()
  ### pushing starting position, direction, score, and path
  ### pq is the distance to the end + the current score
  pq$push(list(st[1],st[2],1,0,c(str_flatten(st,"~"))),-sum(abs(st-en)))
  bestlength<-Inf
  paths<-c()
  closer<-0
  winctr<-0
  while(pq$size()>0){
    currlist<-pq$pop()
    curr<-unlist(currlist[1:4])
    pth<-unlist(currlist[5])
    ### if the current score > bestlength - stop
    if(curr[4]>bestlength){break}
    ### if at the end
    if(all(curr[1:2]==en)){
      ### if this is shorter than the best length
      if(curr[4]<bestlength){
        ### make this the new bestlength
        bestlength<-curr[4]
        ### this is the new best path list (should only happen once, but just in case)
        paths<-pth
        ### if this matches the best length
      }else if(curr[4]==bestlength){
        ### add this path to the list of path seats
        paths<-c(paths,pth)}
    next}
    ### check if we've been there faster - if faster, drop - if slower or equal, keep going
    if(beenthere$has(str_flatten(curr[1:3],"~"))){
      when<-beenthere$get(str_flatten(curr[1:3],"~"))
      if(when<curr[4]){next}}
    beenthere$set(str_flatten(curr[1:3],"~"),curr[4])
    ### turn clockwise & counterclockwise
    pq$push(list(curr[1],curr[2],(curr[3]+1)%%4,curr[4]+1000,pth),-sum(abs(en-curr[1:2]),curr[4]))
    pq$push(list(curr[1],curr[2],(curr[3]-1)%%4,curr[4]+1000,pth),-sum(abs(en-curr[1:2]),curr[4]))
    ### move, depending on which direction currently facing
    nxt<-FALSE
    d<-as.character(curr[3])
    switch(d,
           "0"=if(!mz$has(str_flatten(curr[1:2]+c(-1,0),"~"))){nxt<-curr[1:2]+c(-1,0)},
           "1"=if(!mz$has(str_flatten(curr[1:2]+c(0,1),"~"))){nxt<-curr[1:2]+c(0,1)},
           "2"=if(!mz$has(str_flatten(curr[1:2]+c(1,0),"~"))){nxt<-curr[1:2]+c(1,0)},
           "3"=if(!mz$has(str_flatten(curr[1:2]+c(0,-1),"~"))){nxt<-curr[1:2]+c(0,-1)},
           cat("bad direction\n"))
    if(!any(nxt==FALSE)){
      pq$push(list(nxt[1],nxt[2],curr[3],curr[4]+1,c(pth,str_flatten(nxt,"~"))),-sum(abs(en-nxt),curr[4]))}}
  unique(paths)}
p2<-bestseat(reindeermaze,reinstart,reinend)
part2<-length(p2)
part2
[1] 45
Best Paths

Best Paths

LS0tDQp0aXRsZTogIkRheSAxNiBOb3RlYm9vayINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShnZ2FuaW1hdGUpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHJlc2hhcGUyKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGNvbGxlY3Rpb25zKQ0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpDQpgYGANCg0KYGBge3J9DQppbnB1dDwtcmVhZF9saW5lcygiRGF5MTZTYW1wbGUxLnR4dCIpDQojIyMgbWFrZSB0aGUgbWF6ZSBpbnRvIGEgZGljdCwgZmluZCB0aGUgc3RhcnQgYW5kIGVuZA0KcmVpbmRlZXJtYXplPC1kaWN0KCkNCmZvcihpIGluIDE6bGVuZ3RoKGlucHV0KSl7DQogIHg8LXVubGlzdChzdHJfc3BsaXQoaW5wdXRbaV0sIiIpKQ0KICBmb3IoaiBpbiAxOmxlbmd0aCh4KSl7DQogICAgc3dpdGNoKHhbal0sDQogICAgICAgICAgICIjIj1yZWluZGVlcm1hemUkc2V0KHN0cl9mbGF0dGVuKGMoaSxqKSwifiIpLDApLA0KICAgICAgICAgICAiUyI9cmVpbnN0YXJ0PC1jKGksaiksDQogICAgICAgICAgICJFIj1yZWluZW5kPC1jKGksaiksDQogICAgICAgICAgIHt9KX19DQpgYGANCg0KDQojIyBQYXJ0IDENCkp1c3QgYSB2ZXJ5LCB2ZXJ5IHN0cmFpZ2h0Zm9yd2FyZCBzZWFyY2ggLSANCg0KTj0wDQpFPTENClM9Mg0KVz0zDQoNCmBgYHtyfQ0KbWF6ZXBhdGg8LWZ1bmN0aW9uKG16LHN0LGVuKXsNCiAgYmVlbnRoZXJlPC1kaWN0KCkNCiAgcHE8LXByaW9yaXR5X3F1ZXVlKCkNCiAgIyMjIHB1c2hpbmcgc3RhcnRpbmcgcG9zaXRpb24sIGRpcmVjdGlvbiwgJiBzY29yZQ0KICAjIyMgcHEgaXMgdGhlIGRpc3RhbmNlIHRvIHRoZSBlbmQgKyB0aGUgY3VycmVudCBzY29yZSANCiAgcHEkcHVzaChjKHN0LDEsMCksLXN1bShhYnMoc3QtZW4pKSkNCiAgd2hpbGUocHEkc2l6ZSgpPjApew0KICAgIGN1cnI8LXBxJHBvcCgpDQogICAgIyMjIGlmIGF0IHRoZSBlbmQsIGxlYXZlDQogICAgaWYoYWxsKGN1cnJbMToyXT09ZW4pKXtyZXR1cm4oY3Vycls0XSl9DQogICAgIyMjIGlmIGhhdmUgYmVlbiB0aGVyZSBmYWNpbmcgdGhhdCBkaXJlY3Rpb24sIHN0b3ANCiAgICBpZihiZWVudGhlcmUkaGFzKHN0cl9mbGF0dGVuKGN1cnJbMTozXSwifiIpKSl7bmV4dH0NCiAgICBiZWVudGhlcmUkc2V0KHN0cl9mbGF0dGVuKGN1cnJbMTozXSwifiIpLDApDQogICAgIyMjIHR1cm4gY2xvY2t3aXNlICYgY291bnRlcmNsb2Nrd2lzZQ0KICAgIHBxJHB1c2goYyhjdXJyWzE6Ml0sKGN1cnJbM10rMSklJTQsY3Vycls0XSsxMDAwKSwtc3VtKGFicyhlbi1jdXJyWzE6Ml0pLGN1cnJbNF0pKQ0KICAgIHBxJHB1c2goYyhjdXJyWzE6Ml0sKGN1cnJbM10tMSklJTQsY3Vycls0XSsxMDAwKSwtc3VtKGFicyhlbi1jdXJyWzE6Ml0pLGN1cnJbNF0pKQ0KICAgICMjIyBtb3ZlLCBkZXBlbmRpbmcgb24gd2hpY2ggZGlyZWN0aW9uIGN1cnJlbnRseSBmYWNpbmcNCiAgICBueHQ8LUZBTFNFDQogICAgZDwtYXMuY2hhcmFjdGVyKGN1cnJbM10pDQogICAgc3dpdGNoKGQsDQogICAgICAgICAgICIwIj1pZighbXokaGFzKHN0cl9mbGF0dGVuKGN1cnJbMToyXStjKC0xLDApLCJ+IikpKXtueHQ8LWN1cnJbMToyXStjKC0xLDApfSwNCiAgICAgICAgICAgIjEiPWlmKCFteiRoYXMoc3RyX2ZsYXR0ZW4oY3VyclsxOjJdK2MoMCwxKSwifiIpKSl7bnh0PC1jdXJyWzE6Ml0rYygwLDEpfSwNCiAgICAgICAgICAgIjIiPWlmKCFteiRoYXMoc3RyX2ZsYXR0ZW4oY3VyclsxOjJdK2MoMSwwKSwifiIpKSl7bnh0PC1jdXJyWzE6Ml0rYygxLDApfSwNCiAgICAgICAgICAgIjMiPWlmKCFteiRoYXMoc3RyX2ZsYXR0ZW4oY3VyclsxOjJdK2MoMCwtMSksIn4iKSkpe254dDwtY3VyclsxOjJdK2MoMCwtMSl9LA0KICAgICAgICAgICBjYXQoImJhZCBkaXJlY3Rpb25cbiIpKQ0KICAgIGlmKCFhbnkobnh0PT1GQUxTRSkpew0KICAgICAgcHEkcHVzaChjKG54dCxjdXJyWzNdLGN1cnJbNF0rMSksLXN1bShhYnMoZW4tbnh0KSxjdXJyWzRdKSl9fQ0KICBiZWVudGhlcmV9DQpgYGANCg0KDQpgYGB7cn0NCnBhcnQxPC1tYXplcGF0aChyZWluZGVlcm1hemUscmVpbnN0YXJ0LHJlaW5lbmQpDQpwYXJ0MQ0KYGBgDQojIyBQYXJ0IDINCkJlY2F1c2UgSSBuZWVkIHRvIHNhdmUgdGhlIHBhdGggZHVyaW5nIHRoZSBzZWFyY2ggKGFuZCByZXR1cm4gYWxsIHBhdGhzKSwgSSBuZWVkIHRvIG1ha2Ugc29tZSBzbWFsbCBjaGFuZ2VzOg0KDQpgYGB7cn0NCmJlc3RzZWF0PC1mdW5jdGlvbihteixzdCxlbil7DQogIGJlZW50aGVyZTwtZGljdCgpDQogIHBxPC1wcmlvcml0eV9xdWV1ZSgpDQogICMjIyBwdXNoaW5nIHN0YXJ0aW5nIHBvc2l0aW9uLCBkaXJlY3Rpb24sIHNjb3JlLCBhbmQgcGF0aA0KICAjIyMgcHEgaXMgdGhlIGRpc3RhbmNlIHRvIHRoZSBlbmQgKyB0aGUgY3VycmVudCBzY29yZQ0KICBwcSRwdXNoKGxpc3Qoc3RbMV0sc3RbMl0sMSwwLGMoc3RyX2ZsYXR0ZW4oc3QsIn4iKSkpLC1zdW0oYWJzKHN0LWVuKSkpDQogIGJlc3RsZW5ndGg8LUluZg0KICBwYXRoczwtYygpDQogIGNsb3NlcjwtMA0KICB3aW5jdHI8LTANCiAgd2hpbGUocHEkc2l6ZSgpPjApew0KICAgIGN1cnJsaXN0PC1wcSRwb3AoKQ0KICAgIGN1cnI8LXVubGlzdChjdXJybGlzdFsxOjRdKQ0KICAgIHB0aDwtdW5saXN0KGN1cnJsaXN0WzVdKQ0KICAgICMjIyBpZiB0aGUgY3VycmVudCBzY29yZSA+IGJlc3RsZW5ndGggLSBzdG9wDQogICAgaWYoY3Vycls0XT5iZXN0bGVuZ3RoKXticmVha30NCiAgICAjIyMgaWYgYXQgdGhlIGVuZA0KICAgIGlmKGFsbChjdXJyWzE6Ml09PWVuKSl7DQogICAgICAjIyMgaWYgdGhpcyBpcyBzaG9ydGVyIHRoYW4gdGhlIGJlc3QgbGVuZ3RoDQogICAgICBpZihjdXJyWzRdPGJlc3RsZW5ndGgpew0KICAgICAgICAjIyMgbWFrZSB0aGlzIHRoZSBuZXcgYmVzdGxlbmd0aA0KICAgICAgICBiZXN0bGVuZ3RoPC1jdXJyWzRdDQogICAgICAgICMjIyB0aGlzIGlzIHRoZSBuZXcgYmVzdCBwYXRoIGxpc3QgKHNob3VsZCBvbmx5IGhhcHBlbiBvbmNlLCBidXQganVzdCBpbiBjYXNlKQ0KICAgICAgICBwYXRoczwtcHRoDQogICAgICAgICMjIyBpZiB0aGlzIG1hdGNoZXMgdGhlIGJlc3QgbGVuZ3RoDQogICAgICB9ZWxzZSBpZihjdXJyWzRdPT1iZXN0bGVuZ3RoKXsNCiAgICAgICAgIyMjIGFkZCB0aGlzIHBhdGggdG8gdGhlIGxpc3Qgb2YgcGF0aCBzZWF0cw0KICAgICAgICBwYXRoczwtYyhwYXRocyxwdGgpfQ0KICAgIG5leHR9DQogICAgIyMjIGNoZWNrIGlmIHdlJ3ZlIGJlZW4gdGhlcmUgZmFzdGVyIC0gaWYgZmFzdGVyLCBkcm9wIC0gaWYgc2xvd2VyIG9yIGVxdWFsLCBrZWVwIGdvaW5nDQogICAgaWYoYmVlbnRoZXJlJGhhcyhzdHJfZmxhdHRlbihjdXJyWzE6M10sIn4iKSkpew0KICAgICAgd2hlbjwtYmVlbnRoZXJlJGdldChzdHJfZmxhdHRlbihjdXJyWzE6M10sIn4iKSkNCiAgICAgIGlmKHdoZW48Y3Vycls0XSl7bmV4dH19DQogICAgYmVlbnRoZXJlJHNldChzdHJfZmxhdHRlbihjdXJyWzE6M10sIn4iKSxjdXJyWzRdKQ0KICAgICMjIyB0dXJuIGNsb2Nrd2lzZSAmIGNvdW50ZXJjbG9ja3dpc2UNCiAgICBwcSRwdXNoKGxpc3QoY3VyclsxXSxjdXJyWzJdLChjdXJyWzNdKzEpJSU0LGN1cnJbNF0rMTAwMCxwdGgpLC1zdW0oYWJzKGVuLWN1cnJbMToyXSksY3Vycls0XSkpDQogICAgcHEkcHVzaChsaXN0KGN1cnJbMV0sY3VyclsyXSwoY3VyclszXS0xKSUlNCxjdXJyWzRdKzEwMDAscHRoKSwtc3VtKGFicyhlbi1jdXJyWzE6Ml0pLGN1cnJbNF0pKQ0KICAgICMjIyBtb3ZlLCBkZXBlbmRpbmcgb24gd2hpY2ggZGlyZWN0aW9uIGN1cnJlbnRseSBmYWNpbmcNCiAgICBueHQ8LUZBTFNFDQogICAgZDwtYXMuY2hhcmFjdGVyKGN1cnJbM10pDQogICAgc3dpdGNoKGQsDQogICAgICAgICAgICIwIj1pZighbXokaGFzKHN0cl9mbGF0dGVuKGN1cnJbMToyXStjKC0xLDApLCJ+IikpKXtueHQ8LWN1cnJbMToyXStjKC0xLDApfSwNCiAgICAgICAgICAgIjEiPWlmKCFteiRoYXMoc3RyX2ZsYXR0ZW4oY3VyclsxOjJdK2MoMCwxKSwifiIpKSl7bnh0PC1jdXJyWzE6Ml0rYygwLDEpfSwNCiAgICAgICAgICAgIjIiPWlmKCFteiRoYXMoc3RyX2ZsYXR0ZW4oY3VyclsxOjJdK2MoMSwwKSwifiIpKSl7bnh0PC1jdXJyWzE6Ml0rYygxLDApfSwNCiAgICAgICAgICAgIjMiPWlmKCFteiRoYXMoc3RyX2ZsYXR0ZW4oY3VyclsxOjJdK2MoMCwtMSksIn4iKSkpe254dDwtY3VyclsxOjJdK2MoMCwtMSl9LA0KICAgICAgICAgICBjYXQoImJhZCBkaXJlY3Rpb25cbiIpKQ0KICAgIGlmKCFhbnkobnh0PT1GQUxTRSkpew0KICAgICAgcHEkcHVzaChsaXN0KG54dFsxXSxueHRbMl0sY3VyclszXSxjdXJyWzRdKzEsYyhwdGgsc3RyX2ZsYXR0ZW4obnh0LCJ+IikpKSwtc3VtKGFicyhlbi1ueHQpLGN1cnJbNF0pKX19DQogIHVuaXF1ZShwYXRocyl9DQpgYGANCg0KDQoNCmBgYHtyfQ0KcDI8LWJlc3RzZWF0KHJlaW5kZWVybWF6ZSxyZWluc3RhcnQscmVpbmVuZCkNCnBhcnQyPC1sZW5ndGgocDIpDQpwYXJ0Mg0KYGBgDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuY2FwPSJCZXN0IFBhdGhzIiwgb3V0LndpZHRoID0gJzUwJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygibWF6ZXJ1bi5naWYiKQ0KYGBgDQoNCmBgYHtyLGluY2x1ZGU9RkFMU0UsZXZhbD1GQUxTRX0NCiMjIyBHcmFwaCBTdHVmZg0KDQoNCmdyZGY8LWFzLmRhdGEuZnJhbWUobWF0cml4KG5yb3c9MCxuY29sPTMpKQ0KaTwtMQ0KY3Q8LTENCndoaWxlKGk8bGVuZ3RoKHAyKSl7DQogIGlmKHAyW2krMV0hPSIxNDB+MiIpew0KICAgIGdyZGY8LXJiaW5kKGdyZGYsYyhwMltpXSxwMltpKzFdLGN0KSkNCiAgICB9ZWxzZXtjdDwtMH0NCiAgaTwtaSsxDQogIGN0PC1jdCsxfQ0KY29sbmFtZXMoZ3JkZik8LWMoInMiLCJlIiwidCIpDQoNCg0KDQoNCmdyZGY8LWdyZGYlPiVyb3d3aXNlJT4lbXV0YXRlKHhzPWFzLm51bWVyaWModW5saXN0KHN0cl9zcGxpdF9pKHMsIn4iLDIpKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ZT1hcy5udW1lcmljKHVubGlzdChzdHJfc3BsaXRfaShlLCJ+IiwyKSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeXM9YXMubnVtZXJpYyh1bmxpc3Qoc3RyX3NwbGl0X2kocywifiIsMSkpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHllPWFzLm51bWVyaWModW5saXN0KHN0cl9zcGxpdF9pKGUsIn4iLDEpKSkpJT4lDQogIHNlbGVjdCgtYyhzLGUpKQ0KDQoNCnF1aWNrZ3JkZjwtdW5pcXVlKGdyZGYpJT4lbXV0YXRlKHQ9YXMubnVtZXJpYyh0KSkNCg0KZ3JiY2s8LWFzLmRhdGEuZnJhbWUobWF0cml4KG5jb2w9Mixucm93PTApKQ0KcmVpbm16a2V5czwtdW5saXN0KGFzLmxpc3QocmVpbmRlZXJtYXplJGtleXMoKSkpDQpmb3IoaSBpbiAxOmxlbmd0aChyZWlubXprZXlzKSl7Z3JiY2s8LXJiaW5kKGdyYmNrLGFzLm51bWVyaWModW5saXN0KHN0cl9zcGxpdChyZWlubXprZXlzW2ldLCJ+IikpKSl9DQpjb2xuYW1lcyhncmJjayk8LWMoIndhbGx5Iiwid2FsbHgiKQ0KDQpyZWlubWF6ZWdyYXBoPC1nZ3Bsb3QocXVpY2tncmRmKSsNCiAgZ2VvbV90aWxlKGRhdGE9Z3JiY2ssYWVzKHg9d2FsbHgseT13YWxseSksY29sb3I9IiM0NDQ0NDQiKSsNCiAgZ2VvbV9zZWdtZW50KGFlcyh4PXhzLHk9eXMseGVuZD14ZSx5ZW5kPXllKSxjb2xvcj0iI0ZGMDAwMCIpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uPSJub25lIikrDQogIHNjYWxlX3lfcmV2ZXJzZSgpKw0KICBjb29yZF9maXhlZCgpKw0KICB0cmFuc2l0aW9uX3N0YXRlcyh0LHdyYXA9RkFMU0UpKw0KICBzaGFkb3dfbWFyaygpDQpyZWlubWF6ZWdyYXBoDQpgYGANCg0K