input<-read_lines("Day15Sample2.txt")
bl<-min(which(input==""))

### create the warehouse
warehouse<-matrix(nrow=(bl-1),ncol=nchar(input[1]))
for(i in 1:(bl-1)){warehouse[i,]<-unlist(str_split(input[i],""))}
### get the instructions
instructions<-c()
for(i in (bl+1):length(input)){
instructions<-c(instructions,unlist(str_split(input[i],"")))}

Part 1

Creating a function - push()

This should take a vector with the wall at 1 & the robot at the end. Will return list - first element is T/F if something could move. Second is the updated, pushed vector.

push<-function(v){
  wall<-max(which(v=="#"))
  if(!("."%in%v)){return(list(FALSE))}
  blnk<-max(which(v=="."))
  ### if there's no blanks before the wall, return FALSE
  if(blnk<wall){return(list(FALSE))}
  ### otherwise, return TRUE
list(TRUE,c(v[-blnk],"."))}

Move the robot

rearrange<-function(w,inst){
  maxx<-ncol(w)
  maxy<-nrow(w)
  ### find the robot starting place
  r<-which(w=="@",arr.ind = TRUE)
  rx<-r[1,2]
  ry<-r[1,1]
  ### run through each instruction
  for(i in 1:length(inst)){
    nxti<-inst[i]
    switch(nxti,
           "^"={
#            cat("^",w[1:ry,rx],"\n")
             up<-push(w[1:ry,rx])
             ## if can't push, go to the next instruction
             if(up[[1]]==FALSE){next
               ### otherwise, move everything & update the robot's place
             }else{w[1:ry,rx]<-up[[2]]
             ry<-ry-1}
           },
           "<"={
 #            cat("<",w[ry,1:rx],"\n")
             left<-push(w[ry,1:rx])
             ## if can't push, go to the next instruction
             if(left[[1]]==FALSE){next
               ### otherwise, move everything & update the robot's place
             }else{w[ry,1:rx]<-left[[2]]
             rx<-rx-1}
           },
           "v"={
#             cat("v",w[maxy:ry,rx],"\n")
             down<-push(w[maxy:ry,rx])
             ## if can't push, go to the next instruction
             if(down[[1]]==FALSE){next
               ### otherwise, move everything & update the robot's place
             }else{w[maxy:ry,rx]<-down[[2]]
             ry<-ry+1}
           },
           ">"={
#             cat(">",w[ry,maxx:rx],"\n")
             right<-push(w[ry,maxx:rx])
             ## if can't push, go to the next instruction
             if(right[[1]]==FALSE){next
               ### otherwise, move everything & update the robot's place
             }else{w[ry,maxx:rx]<-right[[2]]
             rx<-rx+1}
           },
           cat("bad direction\n"))}
  ### calculate gps
  gps<-as.data.frame(which(w=="O",arr.ind=TRUE))
  gps<-gps%>%mutate(crd=100*(row-1)+(col-1))
sum(gps$crd)}
part1<-rearrange(warehouse,instructions)
part1
[1] 10092

Part 2

First, double the width of the warehouse

### create the warehouse
widehouse<-matrix(nrow=(bl-1),ncol=2*nchar(input[1]))
for(i in 1:(bl-1)){
  y<-unlist(str_split(input[i],""))
  y<-sapply(y,function(x){
    switch(x,
           "#"=c("#","#"),
           "O"=c("[","]"),
           "."=c(".","."),
           "@"=c("@","."),
           NA)})
  widehouse[i,]<-y}

Left and right do not change. Up and down, do pushup() & pushdown return FALSE if a move is not possible. They return the robot and any box halves that need to move if it is possible. For sorting purposes, they’re in format y~x and padded with leading 0s to three digits.

pushup<-function(w,x,y){
  chgs<-c()
  u<-w[y-1,x]
  switch(u,
         "."={
           chgs<-str_flatten(str_flatten(c(sprintf("%03d",y),sprintf("%03d",x)),"~"),"~")},
         "#"=return(FALSE),
         "["={
           above<-pushup(w,x,y-1)
           if(above[1]==FALSE){return(FALSE)}
           over<-pushup(w,x+1,y-1)
           if(over[1]==FALSE){return(FALSE)}
           chgs<-c(str_flatten(str_flatten(c(sprintf("%03d",y),sprintf("%03d",x)),"~"),"~"),above,over)},
         "]"={
           above<-pushup(w,x,y-1)
           if(above[1]==FALSE){return(FALSE)}
           over<-pushup(w,x-1,y-1)
           if(over[1]==FALSE){return(FALSE)}
           chgs<-c(str_flatten(str_flatten(c(sprintf("%03d",y),sprintf("%03d",x)),"~"),"~"),above,over)},
         cat("u=",u,"unknown\n"))
  unique(chgs)}

### I should have changed above to below - but I didn't.
pushdown<-function(w,x,y){
  chgs<-c()
  u<-w[y+1,x]
  switch(u,
         "."={
           chgs<-str_flatten(c(sprintf("%03d",y),sprintf("%03d",x)),"~")},
         "#"=return(FALSE),
         "["={
           above<-pushdown(w,x,y+1)
           if(above[1]==FALSE){return(FALSE)}
           over<-pushdown(w,x+1,y+1)
           if(over[1]==FALSE){return(FALSE)}
           chgs<-c(str_flatten(c(sprintf("%03d",y),sprintf("%03d",x)),"~"),above,over)},
         "]"={
           above<-pushdown(w,x,y+1)
           if(above[1]==FALSE){return(FALSE)}
           over<-pushdown(w,x-1,y+1)
           if(over[1]==FALSE){return(FALSE)}
           chgs<-c(str_flatten(c(sprintf("%03d",y),sprintf("%03d",x)),"~"),above,over)},
         cat("d=",u,"unknown\n"))
  unique(chgs)}

For up and down, the rearrangewide() sorts everything that moves and then moves it individually from top to bottom (for up) or bottom to top (for down)

rearrangewide<-function(w,inst){
  maxx<-ncol(w)
  maxy<-nrow(w)
  ### find the robot starting place
  r<-which(w=="@",arr.ind = TRUE)
  rx<-r[1,2]
  ry<-r[1,1]
  ### run through each instruction
  for(i in 1:length(inst)){
    nxti<-inst[i]
    switch(nxti,
           "^"={
#            cat("^",w[1:ry,rx],"\n")
             up<-pushup(w,rx,ry)
             ## if can't push, go to the next instruction
             if(up[1]==FALSE){next
               ### otherwise, move everything & update the robot's place
             }else{
               ### sort up from the top to the bottom
              up<-sort(up)
              for(j in 1:length(up)){
                ### get the coordinate
                u<-unlist(lapply(str_split(up[j],"~"),as.numeric))
                ### copy its value to the row above
                w[(u[1]-1),u[2]]<-w[u[1],u[2]]
                ### put a period there - will be overwritten if something is put into it
                w[u[1],u[2]]<-"."}
              w[ry,rx]<-"."
              ry<-ry-1}
           },
### left doesn't change
           "<"={
             left<-push(w[ry,1:rx])
             ## if can't push, go to the next instruction
             if(left[[1]]==FALSE){next
               ### otherwise, move everything & update the robot's place
             }else{w[ry,1:rx]<-left[[2]]
             rx<-rx-1}
           },
           "v"={
#             cat("v",w[maxy:ry,rx],"\n")
             down<-pushdown(w,rx,ry)
             ## if can't push, go to the next instruction
             if(down[1]==FALSE){next
               ### otherwise, move everything & update the robot's place
             }else{
              down<-sort(down,decreasing=TRUE)
              for(j in 1:length(down)){
                ### get the coordinate
                d<-unlist(lapply(str_split(down[j],"~"),as.numeric))
                ### copy its value to the row above
                w[(d[1]+1),d[2]]<-w[d[1],d[2]]
                w[d[1],d[2]]<-"."}
              w[ry,rx]<-"."
              ry<-ry+1}
           },
### right doesn't change
           ">"={
             right<-push(w[ry,maxx:rx])
             ## if can't push, go to the next instruction
             if(right[[1]]==FALSE){next
               ### otherwise, move everything & update the robot's place
             }else{w[ry,maxx:rx]<-right[[2]]
             rx<-rx+1}
           },
           cat("bad direction\n"))
    
    stillboxes<-which(w=="[")+nrow(w)
    if(any(w[stillboxes]!="]")){return(list(i,nxti,w,stillboxes))}
    stillboxes<-which(w=="]")-nrow(w)
    if(any(w[stillboxes]!="[")){return(list(i,nxti,w,stillboxes))}
    }
  ### calculate gps
  gps<-as.data.frame(which(w=="[",arr.ind=TRUE))
  gps<-gps%>%mutate(crd=100*(row-1)+(col-1))
sum(gps$crd)}
part2<-rearrangewide(widehouse,instructions)
part2
[1] 9021
LS0tDQp0aXRsZTogIkRheSAxNSBOb3RlYm9vayINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShtZW1vaXNlKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShyZXNoYXBlMikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShjb2xsZWN0aW9ucykNCm9wdGlvbnMoc2NpcGVuID0gOTk5KQ0KYGBgDQoNCmBgYHtyfQ0KaW5wdXQ8LXJlYWRfbGluZXMoIkRheTE1U2FtcGxlMi50eHQiKQ0KYmw8LW1pbih3aGljaChpbnB1dD09IiIpKQ0KDQojIyMgY3JlYXRlIHRoZSB3YXJlaG91c2UNCndhcmVob3VzZTwtbWF0cml4KG5yb3c9KGJsLTEpLG5jb2w9bmNoYXIoaW5wdXRbMV0pKQ0KZm9yKGkgaW4gMTooYmwtMSkpe3dhcmVob3VzZVtpLF08LXVubGlzdChzdHJfc3BsaXQoaW5wdXRbaV0sIiIpKX0NCiMjIyBnZXQgdGhlIGluc3RydWN0aW9ucw0KaW5zdHJ1Y3Rpb25zPC1jKCkNCmZvcihpIGluIChibCsxKTpsZW5ndGgoaW5wdXQpKXsNCmluc3RydWN0aW9uczwtYyhpbnN0cnVjdGlvbnMsdW5saXN0KHN0cl9zcGxpdChpbnB1dFtpXSwiIikpKX0NCmBgYA0KDQojIyBQYXJ0IDENCg0KQ3JlYXRpbmcgYSBmdW5jdGlvbiAtIHB1c2goKQ0KDQpUaGlzIHNob3VsZCB0YWtlIGEgdmVjdG9yIHdpdGggdGhlIHdhbGwgYXQgMSAmIHRoZSByb2JvdCBhdCB0aGUgZW5kLiAgV2lsbCByZXR1cm4gbGlzdCAtIGZpcnN0IGVsZW1lbnQgaXMgVC9GIGlmIHNvbWV0aGluZyBjb3VsZCBtb3ZlLiAgU2Vjb25kIGlzIHRoZSB1cGRhdGVkLCBwdXNoZWQgdmVjdG9yLg0KDQpgYGB7cn0NCnB1c2g8LWZ1bmN0aW9uKHYpew0KICB3YWxsPC1tYXgod2hpY2godj09IiMiKSkNCiAgaWYoISgiLiIlaW4ldikpe3JldHVybihsaXN0KEZBTFNFKSl9DQogIGJsbms8LW1heCh3aGljaCh2PT0iLiIpKQ0KICAjIyMgaWYgdGhlcmUncyBubyBibGFua3MgYmVmb3JlIHRoZSB3YWxsLCByZXR1cm4gRkFMU0UNCiAgaWYoYmxuazx3YWxsKXtyZXR1cm4obGlzdChGQUxTRSkpfQ0KICAjIyMgb3RoZXJ3aXNlLCByZXR1cm4gVFJVRQ0KbGlzdChUUlVFLGModlstYmxua10sIi4iKSl9DQpgYGANCg0KDQpNb3ZlIHRoZSByb2JvdA0KYGBge3J9DQpyZWFycmFuZ2U8LWZ1bmN0aW9uKHcsaW5zdCl7DQogIG1heHg8LW5jb2wodykNCiAgbWF4eTwtbnJvdyh3KQ0KICAjIyMgZmluZCB0aGUgcm9ib3Qgc3RhcnRpbmcgcGxhY2UNCiAgcjwtd2hpY2godz09IkAiLGFyci5pbmQgPSBUUlVFKQ0KICByeDwtclsxLDJdDQogIHJ5PC1yWzEsMV0NCiAgIyMjIHJ1biB0aHJvdWdoIGVhY2ggaW5zdHJ1Y3Rpb24NCiAgZm9yKGkgaW4gMTpsZW5ndGgoaW5zdCkpew0KICAgIG54dGk8LWluc3RbaV0NCiAgICBzd2l0Y2gobnh0aSwNCiAgICAgICAgICAgIl4iPXsNCiMgICAgICAgICAgICBjYXQoIl4iLHdbMTpyeSxyeF0sIlxuIikNCiAgICAgICAgICAgICB1cDwtcHVzaCh3WzE6cnkscnhdKQ0KICAgICAgICAgICAgICMjIGlmIGNhbid0IHB1c2gsIGdvIHRvIHRoZSBuZXh0IGluc3RydWN0aW9uDQogICAgICAgICAgICAgaWYodXBbWzFdXT09RkFMU0Upe25leHQNCiAgICAgICAgICAgICAgICMjIyBvdGhlcndpc2UsIG1vdmUgZXZlcnl0aGluZyAmIHVwZGF0ZSB0aGUgcm9ib3QncyBwbGFjZQ0KICAgICAgICAgICAgIH1lbHNle3dbMTpyeSxyeF08LXVwW1syXV0NCiAgICAgICAgICAgICByeTwtcnktMX0NCiAgICAgICAgICAgfSwNCiAgICAgICAgICAgIjwiPXsNCiAjICAgICAgICAgICAgY2F0KCI8Iix3W3J5LDE6cnhdLCJcbiIpDQogICAgICAgICAgICAgbGVmdDwtcHVzaCh3W3J5LDE6cnhdKQ0KICAgICAgICAgICAgICMjIGlmIGNhbid0IHB1c2gsIGdvIHRvIHRoZSBuZXh0IGluc3RydWN0aW9uDQogICAgICAgICAgICAgaWYobGVmdFtbMV1dPT1GQUxTRSl7bmV4dA0KICAgICAgICAgICAgICAgIyMjIG90aGVyd2lzZSwgbW92ZSBldmVyeXRoaW5nICYgdXBkYXRlIHRoZSByb2JvdCdzIHBsYWNlDQogICAgICAgICAgICAgfWVsc2V7d1tyeSwxOnJ4XTwtbGVmdFtbMl1dDQogICAgICAgICAgICAgcng8LXJ4LTF9DQogICAgICAgICAgIH0sDQogICAgICAgICAgICJ2Ij17DQojICAgICAgICAgICAgIGNhdCgidiIsd1ttYXh5OnJ5LHJ4XSwiXG4iKQ0KICAgICAgICAgICAgIGRvd248LXB1c2god1ttYXh5OnJ5LHJ4XSkNCiAgICAgICAgICAgICAjIyBpZiBjYW4ndCBwdXNoLCBnbyB0byB0aGUgbmV4dCBpbnN0cnVjdGlvbg0KICAgICAgICAgICAgIGlmKGRvd25bWzFdXT09RkFMU0Upe25leHQNCiAgICAgICAgICAgICAgICMjIyBvdGhlcndpc2UsIG1vdmUgZXZlcnl0aGluZyAmIHVwZGF0ZSB0aGUgcm9ib3QncyBwbGFjZQ0KICAgICAgICAgICAgIH1lbHNle3dbbWF4eTpyeSxyeF08LWRvd25bWzJdXQ0KICAgICAgICAgICAgIHJ5PC1yeSsxfQ0KICAgICAgICAgICB9LA0KICAgICAgICAgICAiPiI9ew0KIyAgICAgICAgICAgICBjYXQoIj4iLHdbcnksbWF4eDpyeF0sIlxuIikNCiAgICAgICAgICAgICByaWdodDwtcHVzaCh3W3J5LG1heHg6cnhdKQ0KICAgICAgICAgICAgICMjIGlmIGNhbid0IHB1c2gsIGdvIHRvIHRoZSBuZXh0IGluc3RydWN0aW9uDQogICAgICAgICAgICAgaWYocmlnaHRbWzFdXT09RkFMU0Upe25leHQNCiAgICAgICAgICAgICAgICMjIyBvdGhlcndpc2UsIG1vdmUgZXZlcnl0aGluZyAmIHVwZGF0ZSB0aGUgcm9ib3QncyBwbGFjZQ0KICAgICAgICAgICAgIH1lbHNle3dbcnksbWF4eDpyeF08LXJpZ2h0W1syXV0NCiAgICAgICAgICAgICByeDwtcngrMX0NCiAgICAgICAgICAgfSwNCiAgICAgICAgICAgY2F0KCJiYWQgZGlyZWN0aW9uXG4iKSl9DQogICMjIyBjYWxjdWxhdGUgZ3BzDQogIGdwczwtYXMuZGF0YS5mcmFtZSh3aGljaCh3PT0iTyIsYXJyLmluZD1UUlVFKSkNCiAgZ3BzPC1ncHMlPiVtdXRhdGUoY3JkPTEwMCoocm93LTEpKyhjb2wtMSkpDQpzdW0oZ3BzJGNyZCl9DQpgYGANCg0KDQoNCmBgYHtyfQ0KcGFydDE8LXJlYXJyYW5nZSh3YXJlaG91c2UsaW5zdHJ1Y3Rpb25zKQ0KcGFydDENCmBgYA0KIyMgUGFydCAyDQoNCkZpcnN0LCBkb3VibGUgdGhlIHdpZHRoIG9mIHRoZSB3YXJlaG91c2UNCg0KYGBge3J9DQojIyMgY3JlYXRlIHRoZSB3YXJlaG91c2UNCndpZGVob3VzZTwtbWF0cml4KG5yb3c9KGJsLTEpLG5jb2w9MipuY2hhcihpbnB1dFsxXSkpDQpmb3IoaSBpbiAxOihibC0xKSl7DQogIHk8LXVubGlzdChzdHJfc3BsaXQoaW5wdXRbaV0sIiIpKQ0KICB5PC1zYXBwbHkoeSxmdW5jdGlvbih4KXsNCiAgICBzd2l0Y2goeCwNCiAgICAgICAgICAgIiMiPWMoIiMiLCIjIiksDQogICAgICAgICAgICJPIj1jKCJbIiwiXSIpLA0KICAgICAgICAgICAiLiI9YygiLiIsIi4iKSwNCiAgICAgICAgICAgIkAiPWMoIkAiLCIuIiksDQogICAgICAgICAgIE5BKX0pDQogIHdpZGVob3VzZVtpLF08LXl9DQpgYGANCg0KTGVmdCBhbmQgcmlnaHQgZG8gbm90IGNoYW5nZS4gVXAgYW5kIGRvd24sIGRvDQpwdXNodXAoKSAmIHB1c2hkb3duIHJldHVybiBGQUxTRSBpZiBhIG1vdmUgaXMgbm90IHBvc3NpYmxlLiBUaGV5IHJldHVybiB0aGUgcm9ib3QgYW5kIGFueSBib3ggaGFsdmVzIHRoYXQgbmVlZCB0byBtb3ZlIGlmIGl0IGlzIHBvc3NpYmxlLiAgRm9yIHNvcnRpbmcgcHVycG9zZXMsIHRoZXkncmUgaW4gZm9ybWF0IHl+eCBhbmQgcGFkZGVkIHdpdGggbGVhZGluZyAwcyB0byB0aHJlZSBkaWdpdHMuDQoNCmBgYHtyfQ0KcHVzaHVwPC1mdW5jdGlvbih3LHgseSl7DQogIGNoZ3M8LWMoKQ0KICB1PC13W3ktMSx4XQ0KICBzd2l0Y2godSwNCiAgICAgICAgICIuIj17DQogICAgICAgICAgIGNoZ3M8LXN0cl9mbGF0dGVuKHN0cl9mbGF0dGVuKGMoc3ByaW50ZigiJTAzZCIseSksc3ByaW50ZigiJTAzZCIseCkpLCJ+IiksIn4iKX0sDQogICAgICAgICAiIyI9cmV0dXJuKEZBTFNFKSwNCiAgICAgICAgICJbIj17DQogICAgICAgICAgIGFib3ZlPC1wdXNodXAodyx4LHktMSkNCiAgICAgICAgICAgaWYoYWJvdmVbMV09PUZBTFNFKXtyZXR1cm4oRkFMU0UpfQ0KICAgICAgICAgICBvdmVyPC1wdXNodXAodyx4KzEseS0xKQ0KICAgICAgICAgICBpZihvdmVyWzFdPT1GQUxTRSl7cmV0dXJuKEZBTFNFKX0NCiAgICAgICAgICAgY2hnczwtYyhzdHJfZmxhdHRlbihzdHJfZmxhdHRlbihjKHNwcmludGYoIiUwM2QiLHkpLHNwcmludGYoIiUwM2QiLHgpKSwifiIpLCJ+IiksYWJvdmUsb3Zlcil9LA0KICAgICAgICAgIl0iPXsNCiAgICAgICAgICAgYWJvdmU8LXB1c2h1cCh3LHgseS0xKQ0KICAgICAgICAgICBpZihhYm92ZVsxXT09RkFMU0Upe3JldHVybihGQUxTRSl9DQogICAgICAgICAgIG92ZXI8LXB1c2h1cCh3LHgtMSx5LTEpDQogICAgICAgICAgIGlmKG92ZXJbMV09PUZBTFNFKXtyZXR1cm4oRkFMU0UpfQ0KICAgICAgICAgICBjaGdzPC1jKHN0cl9mbGF0dGVuKHN0cl9mbGF0dGVuKGMoc3ByaW50ZigiJTAzZCIseSksc3ByaW50ZigiJTAzZCIseCkpLCJ+IiksIn4iKSxhYm92ZSxvdmVyKX0sDQogICAgICAgICBjYXQoInU9Iix1LCJ1bmtub3duXG4iKSkNCiAgdW5pcXVlKGNoZ3MpfQ0KDQojIyMgSSBzaG91bGQgaGF2ZSBjaGFuZ2VkIGFib3ZlIHRvIGJlbG93IC0gYnV0IEkgZGlkbid0Lg0KcHVzaGRvd248LWZ1bmN0aW9uKHcseCx5KXsNCiAgY2hnczwtYygpDQogIHU8LXdbeSsxLHhdDQogIHN3aXRjaCh1LA0KICAgICAgICAgIi4iPXsNCiAgICAgICAgICAgY2hnczwtc3RyX2ZsYXR0ZW4oYyhzcHJpbnRmKCIlMDNkIix5KSxzcHJpbnRmKCIlMDNkIix4KSksIn4iKX0sDQogICAgICAgICAiIyI9cmV0dXJuKEZBTFNFKSwNCiAgICAgICAgICJbIj17DQogICAgICAgICAgIGFib3ZlPC1wdXNoZG93bih3LHgseSsxKQ0KICAgICAgICAgICBpZihhYm92ZVsxXT09RkFMU0Upe3JldHVybihGQUxTRSl9DQogICAgICAgICAgIG92ZXI8LXB1c2hkb3duKHcseCsxLHkrMSkNCiAgICAgICAgICAgaWYob3ZlclsxXT09RkFMU0Upe3JldHVybihGQUxTRSl9DQogICAgICAgICAgIGNoZ3M8LWMoc3RyX2ZsYXR0ZW4oYyhzcHJpbnRmKCIlMDNkIix5KSxzcHJpbnRmKCIlMDNkIix4KSksIn4iKSxhYm92ZSxvdmVyKX0sDQogICAgICAgICAiXSI9ew0KICAgICAgICAgICBhYm92ZTwtcHVzaGRvd24odyx4LHkrMSkNCiAgICAgICAgICAgaWYoYWJvdmVbMV09PUZBTFNFKXtyZXR1cm4oRkFMU0UpfQ0KICAgICAgICAgICBvdmVyPC1wdXNoZG93bih3LHgtMSx5KzEpDQogICAgICAgICAgIGlmKG92ZXJbMV09PUZBTFNFKXtyZXR1cm4oRkFMU0UpfQ0KICAgICAgICAgICBjaGdzPC1jKHN0cl9mbGF0dGVuKGMoc3ByaW50ZigiJTAzZCIseSksc3ByaW50ZigiJTAzZCIseCkpLCJ+IiksYWJvdmUsb3Zlcil9LA0KICAgICAgICAgY2F0KCJkPSIsdSwidW5rbm93blxuIikpDQogIHVuaXF1ZShjaGdzKX0NCmBgYA0KDQoNCkZvciB1cCBhbmQgZG93biwgdGhlIHJlYXJyYW5nZXdpZGUoKSBzb3J0cyBldmVyeXRoaW5nIHRoYXQgbW92ZXMgYW5kIHRoZW4gbW92ZXMgaXQgaW5kaXZpZHVhbGx5IGZyb20gdG9wIHRvIGJvdHRvbSAoZm9yIHVwKSBvciBib3R0b20gdG8gdG9wIChmb3IgZG93bikgDQoNCmBgYHtyfQ0KcmVhcnJhbmdld2lkZTwtZnVuY3Rpb24odyxpbnN0KXsNCiAgbWF4eDwtbmNvbCh3KQ0KICBtYXh5PC1ucm93KHcpDQogICMjIyBmaW5kIHRoZSByb2JvdCBzdGFydGluZyBwbGFjZQ0KICByPC13aGljaCh3PT0iQCIsYXJyLmluZCA9IFRSVUUpDQogIHJ4PC1yWzEsMl0NCiAgcnk8LXJbMSwxXQ0KICAjIyMgcnVuIHRocm91Z2ggZWFjaCBpbnN0cnVjdGlvbg0KICBmb3IoaSBpbiAxOmxlbmd0aChpbnN0KSl7DQogICAgbnh0aTwtaW5zdFtpXQ0KICAgIHN3aXRjaChueHRpLA0KICAgICAgICAgICAiXiI9ew0KIyAgICAgICAgICAgIGNhdCgiXiIsd1sxOnJ5LHJ4XSwiXG4iKQ0KICAgICAgICAgICAgIHVwPC1wdXNodXAodyxyeCxyeSkNCiAgICAgICAgICAgICAjIyBpZiBjYW4ndCBwdXNoLCBnbyB0byB0aGUgbmV4dCBpbnN0cnVjdGlvbg0KICAgICAgICAgICAgIGlmKHVwWzFdPT1GQUxTRSl7bmV4dA0KICAgICAgICAgICAgICAgIyMjIG90aGVyd2lzZSwgbW92ZSBldmVyeXRoaW5nICYgdXBkYXRlIHRoZSByb2JvdCdzIHBsYWNlDQogICAgICAgICAgICAgfWVsc2V7DQogICAgICAgICAgICAgICAjIyMgc29ydCB1cCBmcm9tIHRoZSB0b3AgdG8gdGhlIGJvdHRvbQ0KICAgICAgICAgICAgICB1cDwtc29ydCh1cCkNCiAgICAgICAgICAgICAgZm9yKGogaW4gMTpsZW5ndGgodXApKXsNCiAgICAgICAgICAgICAgICAjIyMgZ2V0IHRoZSBjb29yZGluYXRlDQogICAgICAgICAgICAgICAgdTwtdW5saXN0KGxhcHBseShzdHJfc3BsaXQodXBbal0sIn4iKSxhcy5udW1lcmljKSkNCiAgICAgICAgICAgICAgICAjIyMgY29weSBpdHMgdmFsdWUgdG8gdGhlIHJvdyBhYm92ZQ0KICAgICAgICAgICAgICAgIHdbKHVbMV0tMSksdVsyXV08LXdbdVsxXSx1WzJdXQ0KICAgICAgICAgICAgICAgICMjIyBwdXQgYSBwZXJpb2QgdGhlcmUgLSB3aWxsIGJlIG92ZXJ3cml0dGVuIGlmIHNvbWV0aGluZyBpcyBwdXQgaW50byBpdA0KICAgICAgICAgICAgICAgIHdbdVsxXSx1WzJdXTwtIi4ifQ0KICAgICAgICAgICAgICB3W3J5LHJ4XTwtIi4iDQogICAgICAgICAgICAgIHJ5PC1yeS0xfQ0KICAgICAgICAgICB9LA0KIyMjIGxlZnQgZG9lc24ndCBjaGFuZ2UNCiAgICAgICAgICAgIjwiPXsNCiAgICAgICAgICAgICBsZWZ0PC1wdXNoKHdbcnksMTpyeF0pDQogICAgICAgICAgICAgIyMgaWYgY2FuJ3QgcHVzaCwgZ28gdG8gdGhlIG5leHQgaW5zdHJ1Y3Rpb24NCiAgICAgICAgICAgICBpZihsZWZ0W1sxXV09PUZBTFNFKXtuZXh0DQogICAgICAgICAgICAgICAjIyMgb3RoZXJ3aXNlLCBtb3ZlIGV2ZXJ5dGhpbmcgJiB1cGRhdGUgdGhlIHJvYm90J3MgcGxhY2UNCiAgICAgICAgICAgICB9ZWxzZXt3W3J5LDE6cnhdPC1sZWZ0W1syXV0NCiAgICAgICAgICAgICByeDwtcngtMX0NCiAgICAgICAgICAgfSwNCiAgICAgICAgICAgInYiPXsNCiMgICAgICAgICAgICAgY2F0KCJ2Iix3W21heHk6cnkscnhdLCJcbiIpDQogICAgICAgICAgICAgZG93bjwtcHVzaGRvd24odyxyeCxyeSkNCiAgICAgICAgICAgICAjIyBpZiBjYW4ndCBwdXNoLCBnbyB0byB0aGUgbmV4dCBpbnN0cnVjdGlvbg0KICAgICAgICAgICAgIGlmKGRvd25bMV09PUZBTFNFKXtuZXh0DQogICAgICAgICAgICAgICAjIyMgb3RoZXJ3aXNlLCBtb3ZlIGV2ZXJ5dGhpbmcgJiB1cGRhdGUgdGhlIHJvYm90J3MgcGxhY2UNCiAgICAgICAgICAgICB9ZWxzZXsNCiAgICAgICAgICAgICAgZG93bjwtc29ydChkb3duLGRlY3JlYXNpbmc9VFJVRSkNCiAgICAgICAgICAgICAgZm9yKGogaW4gMTpsZW5ndGgoZG93bikpew0KICAgICAgICAgICAgICAgICMjIyBnZXQgdGhlIGNvb3JkaW5hdGUNCiAgICAgICAgICAgICAgICBkPC11bmxpc3QobGFwcGx5KHN0cl9zcGxpdChkb3duW2pdLCJ+IiksYXMubnVtZXJpYykpDQogICAgICAgICAgICAgICAgIyMjIGNvcHkgaXRzIHZhbHVlIHRvIHRoZSByb3cgYWJvdmUNCiAgICAgICAgICAgICAgICB3WyhkWzFdKzEpLGRbMl1dPC13W2RbMV0sZFsyXV0NCiAgICAgICAgICAgICAgICB3W2RbMV0sZFsyXV08LSIuIn0NCiAgICAgICAgICAgICAgd1tyeSxyeF08LSIuIg0KICAgICAgICAgICAgICByeTwtcnkrMX0NCiAgICAgICAgICAgfSwNCiMjIyByaWdodCBkb2Vzbid0IGNoYW5nZQ0KICAgICAgICAgICAiPiI9ew0KICAgICAgICAgICAgIHJpZ2h0PC1wdXNoKHdbcnksbWF4eDpyeF0pDQogICAgICAgICAgICAgIyMgaWYgY2FuJ3QgcHVzaCwgZ28gdG8gdGhlIG5leHQgaW5zdHJ1Y3Rpb24NCiAgICAgICAgICAgICBpZihyaWdodFtbMV1dPT1GQUxTRSl7bmV4dA0KICAgICAgICAgICAgICAgIyMjIG90aGVyd2lzZSwgbW92ZSBldmVyeXRoaW5nICYgdXBkYXRlIHRoZSByb2JvdCdzIHBsYWNlDQogICAgICAgICAgICAgfWVsc2V7d1tyeSxtYXh4OnJ4XTwtcmlnaHRbWzJdXQ0KICAgICAgICAgICAgIHJ4PC1yeCsxfQ0KICAgICAgICAgICB9LA0KICAgICAgICAgICBjYXQoImJhZCBkaXJlY3Rpb25cbiIpKQ0KICAgIA0KICAgIHN0aWxsYm94ZXM8LXdoaWNoKHc9PSJbIikrbnJvdyh3KQ0KICAgIGlmKGFueSh3W3N0aWxsYm94ZXNdIT0iXSIpKXtyZXR1cm4obGlzdChpLG54dGksdyxzdGlsbGJveGVzKSl9DQogICAgc3RpbGxib3hlczwtd2hpY2godz09Il0iKS1ucm93KHcpDQogICAgaWYoYW55KHdbc3RpbGxib3hlc10hPSJbIikpe3JldHVybihsaXN0KGksbnh0aSx3LHN0aWxsYm94ZXMpKX0NCiAgICB9DQogICMjIyBjYWxjdWxhdGUgZ3BzDQogIGdwczwtYXMuZGF0YS5mcmFtZSh3aGljaCh3PT0iWyIsYXJyLmluZD1UUlVFKSkNCiAgZ3BzPC1ncHMlPiVtdXRhdGUoY3JkPTEwMCoocm93LTEpKyhjb2wtMSkpDQpzdW0oZ3BzJGNyZCl9DQpgYGANCg0KYGBge3J9DQpwYXJ0MjwtcmVhcnJhbmdld2lkZSh3aWRlaG91c2UsaW5zdHJ1Y3Rpb25zKQ0KcGFydDINCmBgYA0K