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