Chapter 10 Conditions and Loops

Looks at how you can control the flow and order of execution in your code.

10.1 IF statements

An IF statement runs a block of code ONLY when a certain condition is true.

10.1.1 Stand Alone statements

The condition is enclosed in parenthesis after the IF The condition must yield a single logical value (TRUE or FALSE) If condition is not satisfied, R skips the code inside the bracket and does nothing or continues to execute any code after the closing bracket.

# setup variables
a <-3
mynumber <- 4
a
[1] 3
mynumber
[1] 4
# test condtions
if(a<=mynumber)
{ a<-a^2}
a
[1] 9
# setup variables
myvec <-c(2.73,5.4,2.15,5.29,1.36,2.16,1.41,6.97,7.99,9.52)
myvec
 [1] 2.73 5.40 2.15 5.29 1.36 2.16 1.41 6.97 7.99 9.52
mymat <-matrix(c(2,0,1,2,3,0,3,0,1,1),5,2)
mymat
     [,1] [,2]
[1,]    2    0
[2,]    0    3
[3,]    1    0
[4,]    2    1
[5,]    3    1
# test the if statement
if(any(myvec-1)>9||matrix(myvec,2,5)[2,1]<=6)
  {
         cat("contiion satisfied -- \n")
         new.myvec<-myvec
         new.myvec[seq(1,9,2)] <-NA
         mylist <- list(aa=new.myvec,bb=mymat+0.5)
         cat("--a list with",length(mylist),"members now exists.")
  }
coercing argument of type 'double' to logical
contiion satisfied -- 
--a list with 2 members now exists.
mylist
$aa
 [1]   NA 5.40   NA 5.29   NA 2.16   NA 6.97   NA 9.52

$bb
     [,1] [,2]
[1,]  2.5  0.5
[2,]  0.5  3.5
[3,]  1.5  0.5
[4,]  2.5  1.5
[5,]  3.5  1.5

10.1.2 else Statements

If you want something to execute if a defined condition is FALSE you can add an [else] decalaration.

# setup variables
a <-3
mynumber <-4
a
[1] 3
mynumber
[1] 4
# test if else 
if(a<=mynumber)
{
  cat("Condition was", a<=mynumber)
  a<-a^2
} else
{
  cat("Condition was", a<=mynumber)
  a<-a-3.5
}
Condition was TRUE
# see what a is now
a
[1] 9

10.1.3 Using ifelse for Element-wise Checks

Since [if] statements can only check on a single logical value, you need [ifelse] to perform vector oriented check in relatively simple cases.

# variables
x <-5
y <--5:5
x
[1] 5
y
 [1] -5 -4 -3 -2 -1  0  1  2  3  4  5
# if we were to divide x/y one of them would come up to inf due to divide by zero
y==0
 [1] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE
# using ifelse
result <- ifelse(test=y==0,yes=NA,no=x/y)
result
 [1] -1.000000 -1.250000 -1.666667 -2.500000 -5.000000        NA  5.000000  2.500000  1.666667  1.250000  1.000000

10.1.4 Nesting and Stocking Statements

YOu can next mulitple IF statement inside other IF statements

# set up variable
a<-6
mynumber <-4
if(a<=mynumber)
{
  cat("First Condition was TRUE")
  a<-a^2
  
  if(mynumber>3)
  {
    cat("Second Condition was true")
    b<-seq(1,a,length=mynumber)
    
  } else
  {
    cat("Second Condition was FALSE")
    b<-a*mynumber
  }
     
} else
{
  cat("First Condition was False\n")
  a<-a-3.5
  if(mynumber>=4)
  {
   cat("Second condition was TRUE")
  b<-a^(3-mynumber)
  
}else
{
  cat("Second Condition was False")
  b<-rep(a+mynumber,times=3)
  
}
}
First Condition was False
Second condition was TRUE
# see what a is now
a
[1] 2.5
b
[1] 0.4

10.1.5 The Switch function

Similar to case statement

# set up variable
mystring<-"Lisa"
foo <-switch(EXPR=mystring, Homer=12,Marge=34,Bart=56,Lisa=78,Maggie=90,NA)
foo
[1] 78

For integers, the Switch works using the number to specify the position

# variable
mynum <- 3
foo <-switch(mynum,12,34,56,78,NA)
foo
[1] 56

10.2 Coding Loops

For Loop repeats code as it works its way through a vector While loop simply repeats code until a specific condition evaluates to FALSE

1-.2.1 For loops

General form: for(loopindex in loopvector){} do any code here

loopindex is a placeholder that represents an element in the loopvector. It starts off fromthe first element in the vector and moves to the next element wiht each loop repetition

for(myitem in 5:7){
  cat("--braced area begins -- \n")
  cat("the current item is",myitem,"\n")
  cat("--braced area ends--\n\n")
  
}
--braced area begins -- 
the current item is 5 
--braced area ends--

--braced area begins -- 
the current item is 6 
--braced area ends--

--braced area begins -- 
the current item is 7 
--braced area ends--
# you can use loops to manipulate objects that exists outside the loop
counter <-0
for(myitem in 5:7){
  counter<-counter+1
  cat("--braced area begins -- \n")
  cat("the current item in run",counter, "is ",myitem,"\n")
  cat("--braced area ends--\n\n")
  
}
--braced area begins -- 
the current item in run 1 is  5 
--braced area ends--

--braced area begins -- 
the current item in run 2 is  6 
--braced area ends--

--braced area begins -- 
the current item in run 3 is  7 
--braced area ends--

Looping via Index or Value

myvec <-c(0.4,1.1,0.34,0.55)
for(i in myvec){
  print(2*i)
}
[1] 0.8
[1] 2.2
[1] 0.68
[1] 1.1
# example
myvec <-c(0.4,1.1,0.34,0.55)
for(i in 1:length(myvec)){
  print(2*myvec[i])
}
[1] 0.8
[1] 2.2
[1] 0.68
[1] 1.1

Nesting For loops You can also nest for loops just like [if] statements When a loop is nested, the inner loop is executed in full first before the outer loop loopindex is incremented, at which point the inner loop is executed all over again.

loopvec1 <-5:7
loopvec1
[1] 5 6 7
loopvec2 <- 9:6
loopvec2
[1] 9 8 7 6
foo <-matrix(NA,length(loopvec1),length(loopvec2))
foo
     [,1] [,2] [,3] [,4]
[1,]   NA   NA   NA   NA
[2,]   NA   NA   NA   NA
[3,]   NA   NA   NA   NA
# The following nested loop fills foo wiht the result of mulitplying each integer in loopvec1 by each integer in loopvec2
for(i in 1:length(loopvec1)){
  for(j in 1:length(loopvec2)){
    foo[i,j]<-loopvec1[i]*loopvec2[j]
    print(loopvec1[i])
    print(loopvec2[j])
    print(foo[i,j])
  }
}
[1] 5
[1] 9
[1] 45
[1] 5
[1] 8
[1] 40
[1] 5
[1] 7
[1] 35
[1] 5
[1] 6
[1] 30
[1] 6
[1] 9
[1] 54
[1] 6
[1] 8
[1] 48
[1] 6
[1] 7
[1] 42
[1] 6
[1] 6
[1] 36
[1] 7
[1] 9
[1] 63
[1] 7
[1] 8
[1] 56
[1] 7
[1] 7
[1] 49
[1] 7
[1] 6
[1] 42
loopvec1
[1] 5 6 7
loopvec2
[1] 9 8 7 6
foo<-matrix(NA, length(loopvec1),length(loopvec2))
foo
     [,1] [,2] [,3] [,4]
[1,]   NA   NA   NA   NA
[2,]   NA   NA   NA   NA
[3,]   NA   NA   NA   NA
for(i in 1:length(loopvec1)){
  for(j in 1:i){
    foo[i,j] <-loopvec1[i]+loopvec2[j]
    cat("i=",i,"j=",j,loopvec1[i],loopvec2[j],foo[i,j],"\n")
  }
}
i= 1 j= 1 5 9 14 
i= 2 j= 1 6 9 15 
i= 2 j= 2 6 8 14 
i= 3 j= 1 7 9 16 
i= 3 j= 2 7 8 15 
i= 3 j= 3 7 7 14 
foo
     [,1] [,2] [,3] [,4]
[1,]   14   NA   NA   NA
[2,]   15   14   NA   NA
[3,]   16   15   14   NA

Loops are computationally costly in R. YOu should always try to do this in vector-oriented fashion first.

10.2. while Loops

Unlike [for loops] where you need to know the exact number of times to do the loop, [while loops] can execute while a condition is true.

The general form: while(loopcondition) { do any code in here }

# a simple example
myval <- 5
while(myval<10){
  myval <-myval+1
  cat("\n'myval' is now",myval, "\n")
  cat("'mycondition' is now", myval<10, "\n")
}

'myval' is now 6 
'mycondition' is now TRUE 

'myval' is now 7 
'mycondition' is now TRUE 

'myval' is now 8 
'mycondition' is now TRUE 

'myval' is now 9 
'mycondition' is now TRUE 

'myval' is now 10 
'mycondition' is now FALSE 

10.2.3 Implicit looping with Apply

The [apply] function is one of the most basic form of implicit looping. It takes a funtion and applies it to each margin of an array

# you could use sum to get the totals, but you get the entire totals.
foo <-matrix(1:12,4,3)
foo
sum(foo)

# to get row totals
row.totals <-rep(NA,times=nrow(foo))
for(i in 1:nrow(foo)){
  row.totals[i]<-sum(foo[i,])
}
row.totals
# same row totals but this time using apply function
row.totals2<-apply(X=foo,MARGIN=1,FUN=sum)
row.totals2
[1] 15 18 21 24
# to sum the columns change margin to 2
row.totals2<-apply(X=foo,MARGIN=2,FUN=sum)
row.totals2

tapply is a similar function. It performs operations on subsets of the object of interest, where theose subsets are defined in terms of one or more factor vectors.

dia.url<-"https://www.amstat.org/publications/jse/v9n2/4cdata.txt"
diamonds <-read.table(dia.url)
names(diamonds) <-c("Carat","Color","Clarity","Cert","Price")
diamonds[1:5,]

To add up the total value of the diamonds present for the full data set but separated according to Color, you can use Tapply like this:

tapply(diamonds$Price,INDEX=diamonds$Color,FUN=sum)
     D      E      F      G      H      I 
113598 242349 392485 287702 302866 207001 
  

Lapply is similar to apply but applies to lists.

baz<-list(aa=c(3.4,1),bb=matrix(1:4,2,2),cc=matrix(c(T,T,F,T,F,F),3,2),
          dd="string here",
          ee=matrix(c("red","blue","yellow")))
baz
$aa
[1] 3.4 1.0

$bb
     [,1] [,2]
[1,]    1    3
[2,]    2    4

$cc
      [,1]  [,2]
[1,]  TRUE  TRUE
[2,]  TRUE FALSE
[3,] FALSE FALSE

$dd
[1] "string here"

$ee
     [,1]    
[1,] "red"   
[2,] "blue"  
[3,] "yellow"
lapply(baz,FUN=is.matrix)
$aa
[1] FALSE

$bb
[1] TRUE

$cc
[1] TRUE

$dd
[1] FALSE

$ee
[1] TRUE

The returned value is also a list but in an array form. To return as a vector, use the sapply

sapply(baz,FUN=is.matrix)
   aa    bb    cc    dd    ee 
FALSE  TRUE  TRUE FALSE  TRUE 

You can pass additional functions to the apply function

# added sorting
foo
     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12
apply(foo,1,sort,decreasing=TRUE)
     [,1] [,2] [,3] [,4]
[1,]    9   10   11   12
[2,]    5    6    7    8
[3,]    1    2    3    4

10.3 Other Control Flow Mechanism

10.3.1 Declaring Break or next

To premeptively break out of a loop you can declare [break]

foo <-5
bar <-c(2,3,1.1,4,0,4.1,3)
loop1.result<-rep(NA,length(bar))
loop1.result
[1] NA NA NA NA NA NA NA
for(i in 1:length(bar)){
  temp<-foo/bar[i]
  if(is.finite(temp)){
    loop1.result[i]<-temp
  } else {
    break
  }
}
loop1.result
[1] 2.500000 1.666667 4.545455 1.250000       NA       NA       NA

Using break is a drastic solution mostly for troubleshooting. You can use [Next]

loop2.result<-rep(NA,length(bar))
loop2.result
[1] NA NA NA NA NA NA NA
for(i in 1:length(bar)){
  if(bar[i]==0){
    next()
  }
loop2.result[i]<-foo/bar[i] 
}
loop2.result
[1] 2.500000 1.666667 4.545455 1.250000       NA 1.219512 1.666667

10.3.2 The repeat Statement

Another way to do an operation over and over again is to use [repeat] The general format:

repeat{ do any code here. }

fib.a <-1
fib.b<-1
repeat{
  temp <-fib.a+fib.b
  fib.a<-fib.b
  fib.b <-temp
  cat(fib.b,", ",sep=" ")
  if(fib.b>150){
    cat("breaknow..\n")
    break
  }
}
2 , 3 , 5 , 8 , 13 , 21 , 34 , 55 , 89 , 144 , 233 , breaknow..
LS0tDQp0aXRsZTogIkNoYXB0ZXIgMTAiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KPGgxPiBDaGFwdGVyIDEwIENvbmRpdGlvbnMgYW5kIExvb3BzIDwvaDE+DQpMb29rcyBhdCBob3cgeW91IGNhbiBjb250cm9sIHRoZSBmbG93IGFuZCBvcmRlciBvZiBleGVjdXRpb24gaW4geW91ciBjb2RlLiANCg0KPGgyPiAxMC4xIElGIHN0YXRlbWVudHMgPC9oMj4NCkFuIElGIHN0YXRlbWVudCBydW5zIGEgYmxvY2sgb2YgY29kZSBPTkxZIHdoZW4gYSBjZXJ0YWluIGNvbmRpdGlvbiBpcyB0cnVlLg0KDQo8aDM+IDEwLjEuMSBTdGFuZCBBbG9uZSBzdGF0ZW1lbnRzIDwvaDM+DQpUaGUgY29uZGl0aW9uIGlzIGVuY2xvc2VkIGluIHBhcmVudGhlc2lzIGFmdGVyIHRoZSBJRiANClRoZSBjb25kaXRpb24gbXVzdCB5aWVsZCBhIHNpbmdsZSBsb2dpY2FsIHZhbHVlIChUUlVFIG9yIEZBTFNFKQ0KSWYgY29uZGl0aW9uIGlzIG5vdCBzYXRpc2ZpZWQsIFIgc2tpcHMgdGhlIGNvZGUgaW5zaWRlIHRoZSBicmFja2V0IGFuZCBkb2VzIG5vdGhpbmcNCm9yIGNvbnRpbnVlcyB0byBleGVjdXRlIGFueSBjb2RlIGFmdGVyIHRoZSBjbG9zaW5nIGJyYWNrZXQuDQpgYGB7cn0NCiMgc2V0dXAgdmFyaWFibGVzDQphIDwtMw0KbXludW1iZXIgPC0gNA0KYQ0KbXludW1iZXINCg0KIyB0ZXN0IGNvbmR0aW9ucw0KaWYoYTw9bXludW1iZXIpDQp7IGE8LWFeMn0NCg0KYQ0KDQoNCmBgYA0KYGBge3J9DQojIHNldHVwIHZhcmlhYmxlcw0KbXl2ZWMgPC1jKDIuNzMsNS40LDIuMTUsNS4yOSwxLjM2LDIuMTYsMS40MSw2Ljk3LDcuOTksOS41MikNCm15dmVjDQpteW1hdCA8LW1hdHJpeChjKDIsMCwxLDIsMywwLDMsMCwxLDEpLDUsMikNCm15bWF0DQoNCiMgdGVzdCB0aGUgaWYgc3RhdGVtZW50DQppZihhbnkobXl2ZWMtMSk+OXx8bWF0cml4KG15dmVjLDIsNSlbMiwxXTw9NikNCiAgew0KICAgICAgICAgY2F0KCJjb250aWlvbiBzYXRpc2ZpZWQgLS0gXG4iKQ0KICAgICAgICAgbmV3Lm15dmVjPC1teXZlYw0KICAgICAgICAgbmV3Lm15dmVjW3NlcSgxLDksMildIDwtTkENCiAgICAgICAgIG15bGlzdCA8LSBsaXN0KGFhPW5ldy5teXZlYyxiYj1teW1hdCswLjUpDQogICAgICAgICBjYXQoIi0tYSBsaXN0IHdpdGgiLGxlbmd0aChteWxpc3QpLCJtZW1iZXJzIG5vdyBleGlzdHMuIikNCiAgfQ0KbXlsaXN0DQpgYGANCg0KDQoNCjxoMz4gMTAuMS4yIGVsc2UgU3RhdGVtZW50cyA8L2gzPg0KSWYgeW91IHdhbnQgc29tZXRoaW5nIHRvIGV4ZWN1dGUgaWYgYSBkZWZpbmVkIGNvbmRpdGlvbiBpcyBGQUxTRQ0KeW91IGNhbiBhZGQgYW4gW2Vsc2VdIGRlY2FsYXJhdGlvbi4NCg0KYGBge3J9DQojIHNldHVwIHZhcmlhYmxlcw0KYSA8LTMNCm15bnVtYmVyIDwtNA0KYQ0KbXludW1iZXINCg0KIyB0ZXN0IGlmIGVsc2UgDQppZihhPD1teW51bWJlcikNCnsNCiAgY2F0KCJDb25kaXRpb24gd2FzIiwgYTw9bXludW1iZXIpDQogIGE8LWFeMg0KfSBlbHNlDQp7DQogIGNhdCgiQ29uZGl0aW9uIHdhcyIsIGE8PW15bnVtYmVyKQ0KICBhPC1hLTMuNQ0KfQ0KDQojIHNlZSB3aGF0IGEgaXMgbm93DQphDQoNCmBgYA0KDQoNCg0KPGgzPjEwLjEuMyAgVXNpbmcgaWZlbHNlIGZvciBFbGVtZW50LXdpc2UgQ2hlY2tzIDwvaDM+DQpTaW5jZSBbaWZdIHN0YXRlbWVudHMgY2FuIG9ubHkgY2hlY2sgb24gYSBzaW5nbGUgbG9naWNhbCB2YWx1ZSwgeW91IG5lZWQgW2lmZWxzZV0gdG8gcGVyZm9ybSANCnZlY3RvciBvcmllbnRlZCBjaGVjayBpbiByZWxhdGl2ZWx5IHNpbXBsZSBjYXNlcy4NCg0KYGBge3J9DQojIHZhcmlhYmxlcw0KeCA8LTUNCnkgPC0tNTo1DQp4DQp5DQoNCiMgaWYgd2Ugd2VyZSB0byBkaXZpZGUgeC95IG9uZSBvZiB0aGVtIHdvdWxkIGNvbWUgdXAgdG8gaW5mIGR1ZSB0byBkaXZpZGUgYnkgemVybw0KeT09MA0KDQojIHVzaW5nIGlmZWxzZQ0KcmVzdWx0IDwtIGlmZWxzZSh0ZXN0PXk9PTAseWVzPU5BLG5vPXgveSkNCnJlc3VsdA0KYGBgDQoNCg0KPGgzPiAxMC4xLjQgTmVzdGluZyBhbmQgU3RvY2tpbmcgU3RhdGVtZW50cyA8L2gzPg0KWU91IGNhbiBuZXh0IG11bGl0cGxlIElGIHN0YXRlbWVudCBpbnNpZGUgb3RoZXIgSUYgc3RhdGVtZW50cw0KDQoNCmBgYHtyfQ0KIyBzZXQgdXAgdmFyaWFibGUNCg0KYTwtNg0KbXludW1iZXIgPC00DQppZihhPD1teW51bWJlcikNCnsNCiAgY2F0KCJGaXJzdCBDb25kaXRpb24gd2FzIFRSVUUiKQ0KICBhPC1hXjINCg0KICANCiAgaWYobXludW1iZXI+MykNCiAgew0KICAgIGNhdCgiU2Vjb25kIENvbmRpdGlvbiB3YXMgdHJ1ZSIpDQogICAgYjwtc2VxKDEsYSxsZW5ndGg9bXludW1iZXIpDQogICAgDQogIH0gZWxzZQ0KICB7DQogICAgY2F0KCJTZWNvbmQgQ29uZGl0aW9uIHdhcyBGQUxTRSIpDQogICAgYjwtYSpteW51bWJlcg0KICB9DQoNCiAgICAgDQp9IGVsc2UNCnsNCiAgY2F0KCJGaXJzdCBDb25kaXRpb24gd2FzIEZhbHNlXG4iKQ0KICBhPC1hLTMuNQ0KICBpZihteW51bWJlcj49NCkNCiAgew0KICAgY2F0KCJTZWNvbmQgY29uZGl0aW9uIHdhcyBUUlVFIikNCiAgYjwtYV4oMy1teW51bWJlcikNCiAgDQp9ZWxzZQ0Kew0KICBjYXQoIlNlY29uZCBDb25kaXRpb24gd2FzIEZhbHNlIikNCiAgYjwtcmVwKGErbXludW1iZXIsdGltZXM9MykNCiAgDQp9DQp9DQoNCiMgc2VlIHdoYXQgYSBpcyBub3cNCmENCmINCg0KDQoNCmBgYA0KDQpgYGB7cn0NCg0KYGBgDQoNCg0KPGgzPiAxMC4xLjUgVGhlIFN3aXRjaCBmdW5jdGlvbiA8L2gzPg0KU2ltaWxhciB0byBjYXNlIHN0YXRlbWVudA0KDQpgYGB7cn0NCiMgc2V0IHVwIHZhcmlhYmxlDQpteXN0cmluZzwtIkxpc2EiDQpmb28gPC1zd2l0Y2goRVhQUj1teXN0cmluZywgSG9tZXI9MTIsTWFyZ2U9MzQsQmFydD01NixMaXNhPTc4LE1hZ2dpZT05MCxOQSkNCmZvbw0KDQpgYGANCg0KRm9yIGludGVnZXJzLCB0aGUgU3dpdGNoIHdvcmtzIHVzaW5nIHRoZSBudW1iZXIgdG8gc3BlY2lmeSB0aGUgcG9zaXRpb24NCg0KYGBge3J9DQojIHZhcmlhYmxlDQpteW51bSA8LSAzDQpmb28gPC1zd2l0Y2gobXludW0sMTIsMzQsNTYsNzgsTkEpDQpmb28NCg0KYGBgDQoNCjxoMj4gMTAuMiBDb2RpbmcgTG9vcHM8L2gyPg0KRm9yIExvb3AgcmVwZWF0cyBjb2RlIGFzIGl0IHdvcmtzIGl0cyB3YXkgdGhyb3VnaCBhIHZlY3Rvcg0KV2hpbGUgbG9vcCBzaW1wbHkgcmVwZWF0cyBjb2RlIHVudGlsIGEgc3BlY2lmaWMgY29uZGl0aW9uIGV2YWx1YXRlcyB0byBGQUxTRQ0KDQo8aDM+IDEtLjIuMSBGb3IgbG9vcHMgPC9oMz4NCkdlbmVyYWwgZm9ybToNCmZvcihsb29waW5kZXggaW4gbG9vcHZlY3Rvcil7fQ0KIGRvIGFueSBjb2RlIGhlcmUNCiANCiANCiBsb29waW5kZXggaXMgYSBwbGFjZWhvbGRlciB0aGF0IHJlcHJlc2VudHMgYW4gZWxlbWVudCBpbiB0aGUgbG9vcHZlY3Rvci4NCiBJdCBzdGFydHMgb2ZmIGZyb210aGUgZmlyc3QgZWxlbWVudCBpbiB0aGUgdmVjdG9yIGFuZCBtb3ZlcyB0byB0aGUgbmV4dCBlbGVtZW50IHdpaHQgZWFjaCBsb29wIHJlcGV0aXRpb24NCiANCiANCmBgYHtyfQ0KZm9yKG15aXRlbSBpbiA1Ojcpew0KICBjYXQoIi0tYnJhY2VkIGFyZWEgYmVnaW5zIC0tIFxuIikNCiAgY2F0KCJ0aGUgY3VycmVudCBpdGVtIGlzIixteWl0ZW0sIlxuIikNCiAgY2F0KCItLWJyYWNlZCBhcmVhIGVuZHMtLVxuXG4iKQ0KICANCn0NCmBgYA0KYGBge3J9DQojIHlvdSBjYW4gdXNlIGxvb3BzIHRvIG1hbmlwdWxhdGUgb2JqZWN0cyB0aGF0IGV4aXN0cyBvdXRzaWRlIHRoZSBsb29wDQpjb3VudGVyIDwtMA0KZm9yKG15aXRlbSBpbiA1Ojcpew0KICBjb3VudGVyPC1jb3VudGVyKzENCiAgY2F0KCItLWJyYWNlZCBhcmVhIGJlZ2lucyAtLSBcbiIpDQogIGNhdCgidGhlIGN1cnJlbnQgaXRlbSBpbiBydW4iLGNvdW50ZXIsICJpcyAiLG15aXRlbSwiXG4iKQ0KICBjYXQoIi0tYnJhY2VkIGFyZWEgZW5kcy0tXG5cbiIpDQogIA0KfQ0KYGBgDQoNCjxiPkxvb3BpbmcgdmlhIEluZGV4IG9yIFZhbHVlPC9iPg0KDQpgYGB7cn0NCiMgZXhhbXBsZSBvZiBsb29waW5kZXggDQpteXZlYyA8LWMoMC40LDEuMSwwLjM0LDAuNTUpDQpmb3IoaSBpbiBteXZlYyl7DQogIHByaW50KDIqaSkNCn0NCmBgYA0KYGBge3J9DQojIGV4YW1wbGUNCm15dmVjIDwtYygwLjQsMS4xLDAuMzQsMC41NSkNCmZvcihpIGluIDE6bGVuZ3RoKG15dmVjKSl7DQogIHByaW50KDIqbXl2ZWNbaV0pDQp9DQoNCmBgYA0KDQoNCjxiPiBOZXN0aW5nIEZvciBsb29wcyA8Yj4NCllvdSBjYW4gYWxzbyBuZXN0IGZvciBsb29wcyBqdXN0IGxpa2UgW2lmXSBzdGF0ZW1lbnRzDQpXaGVuIGEgbG9vcCBpcyBuZXN0ZWQsIHRoZSBpbm5lciBsb29wIGlzIGV4ZWN1dGVkIGluIGZ1bGwgZmlyc3QgYmVmb3JlIHRoZSBvdXRlciBsb29wIGxvb3BpbmRleCBpcyBpbmNyZW1lbnRlZCwgYXQgd2hpY2ggcG9pbnQgdGhlIGlubmVyIGxvb3AgaXMgZXhlY3V0ZWQgYWxsIG92ZXIgYWdhaW4uIA0KDQpgYGB7cn0NCmxvb3B2ZWMxIDwtNTo3DQpsb29wdmVjMQ0KbG9vcHZlYzIgPC0gOTo2DQpsb29wdmVjMg0KZm9vIDwtbWF0cml4KE5BLGxlbmd0aChsb29wdmVjMSksbGVuZ3RoKGxvb3B2ZWMyKSkNCmZvbw0KDQpgYGANCg0KYGBge3J9DQojIFRoZSBmb2xsb3dpbmcgbmVzdGVkIGxvb3AgZmlsbHMgZm9vIHdpaHQgdGhlIHJlc3VsdCBvZiBtdWxpdHBseWluZyBlYWNoIGludGVnZXIgaW4gbG9vcHZlYzEgYnkgZWFjaCBpbnRlZ2VyIGluIGxvb3B2ZWMyDQoNCmZvcihpIGluIDE6bGVuZ3RoKGxvb3B2ZWMxKSl7DQogIGZvcihqIGluIDE6bGVuZ3RoKGxvb3B2ZWMyKSl7DQogICAgZm9vW2ksal08LWxvb3B2ZWMxW2ldKmxvb3B2ZWMyW2pdDQogICAgcHJpbnQobG9vcHZlYzFbaV0pDQogICAgcHJpbnQobG9vcHZlYzJbal0pDQogICAgcHJpbnQoZm9vW2ksal0pDQogIH0NCn0NCg0KDQoNCmBgYA0KYGBge3J9DQpsb29wdmVjMQ0KbG9vcHZlYzINCmZvbzwtbWF0cml4KE5BLCBsZW5ndGgobG9vcHZlYzEpLGxlbmd0aChsb29wdmVjMikpDQpmb28NCmZvcihpIGluIDE6bGVuZ3RoKGxvb3B2ZWMxKSl7DQogIGZvcihqIGluIDE6aSl7DQogICAgZm9vW2ksal0gPC1sb29wdmVjMVtpXStsb29wdmVjMltqXQ0KICAgIGNhdCgiaT0iLGksImo9IixqLGxvb3B2ZWMxW2ldLGxvb3B2ZWMyW2pdLGZvb1tpLGpdLCJcbiIpDQogIH0NCn0NCmZvbw0KYGBgDQpMb29wcyBhcmUgY29tcHV0YXRpb25hbGx5IGNvc3RseSBpbiBSLiBZT3Ugc2hvdWxkIGFsd2F5cyB0cnkgdG8gZG8gdGhpcyBpbiB2ZWN0b3Itb3JpZW50ZWQgZmFzaGlvbiBmaXJzdC4NCg0KDQo8aDM+IDEwLjIuIHdoaWxlIExvb3BzIDwvaDM+DQpVbmxpa2UgW2ZvciBsb29wc10gd2hlcmUgeW91IG5lZWQgdG8ga25vdyB0aGUgZXhhY3QgbnVtYmVyIG9mIHRpbWVzIHRvIGRvIHRoZSBsb29wLCBbd2hpbGUgbG9vcHNdIGNhbiBleGVjdXRlIHdoaWxlIGEgY29uZGl0aW9uIGlzIHRydWUuDQoNClRoZSBnZW5lcmFsIGZvcm06DQp3aGlsZShsb29wY29uZGl0aW9uKQ0Kew0KZG8gYW55IGNvZGUgaW4gaGVyZQ0KfQ0KDQoNCmBgYHtyfQ0KIyBhIHNpbXBsZSBleGFtcGxlDQpteXZhbCA8LSA1DQp3aGlsZShteXZhbDwxMCl7DQogIG15dmFsIDwtbXl2YWwrMQ0KICBjYXQoIlxuJ215dmFsJyBpcyBub3ciLG15dmFsLCAiXG4iKQ0KICBjYXQoIidteWNvbmRpdGlvbicgaXMgbm93IiwgbXl2YWw8MTAsICJcbiIpDQp9DQoNCmBgYA0KDQo8aDM+IDEwLjIuMyBJbXBsaWNpdCBsb29waW5nIHdpdGggQXBwbHkgPC9oMz4NClRoZSBbYXBwbHldIGZ1bmN0aW9uIGlzIG9uZSBvZiB0aGUgbW9zdCBiYXNpYyBmb3JtIG9mIGltcGxpY2l0IGxvb3BpbmcuDQpJdCB0YWtlcyBhIGZ1bnRpb24gYW5kIGFwcGxpZXMgaXQgdG8gZWFjaCBtYXJnaW4gb2YgYW4gYXJyYXkNCg0KYGBge3J9DQojIHlvdSBjb3VsZCB1c2Ugc3VtIHRvIGdldCB0aGUgdG90YWxzLCBidXQgeW91IGdldCB0aGUgZW50aXJlIHRvdGFscy4NCmZvbyA8LW1hdHJpeCgxOjEyLDQsMykNCmZvbw0Kc3VtKGZvbykNCg0KIyB0byBnZXQgcm93IHRvdGFscw0Kcm93LnRvdGFscyA8LXJlcChOQSx0aW1lcz1ucm93KGZvbykpDQpmb3IoaSBpbiAxOm5yb3coZm9vKSl7DQogIHJvdy50b3RhbHNbaV08LXN1bShmb29baSxdKQ0KfQ0Kcm93LnRvdGFscw0KDQpgYGANCg0KDQpgYGB7cn0NCiMgc2FtZSByb3cgdG90YWxzIGJ1dCB0aGlzIHRpbWUgdXNpbmcgYXBwbHkgZnVuY3Rpb24NCiMgbm90ZSB0aGUgeCBtdXN0IGJlIENhcGl0YWwgWA0KDQpyb3cudG90YWxzMjwtYXBwbHkoWD1mb28sTUFSR0lOPTEsRlVOPXN1bSkNCnJvdy50b3RhbHMyDQoNCmBgYA0KDQoNCmBgYHtyfQ0KIyB0byBzdW0gdGhlIGNvbHVtbnMgY2hhbmdlIG1hcmdpbiB0byAyDQpyb3cudG90YWxzMjwtYXBwbHkoWD1mb28sTUFSR0lOPTIsRlVOPXN1bSkNCnJvdy50b3RhbHMyDQpgYGANCg0KDQp0YXBwbHkgaXMgYSBzaW1pbGFyIGZ1bmN0aW9uLiBJdCBwZXJmb3JtcyBvcGVyYXRpb25zIG9uIHN1YnNldHMgb2YgdGhlIG9iamVjdCBvZiBpbnRlcmVzdCwgd2hlcmUgdGhlb3NlIHN1YnNldHMgYXJlIGRlZmluZWQgaW4gdGVybXMgb2Ygb25lIG9yIG1vcmUgZmFjdG9yIHZlY3RvcnMuIA0KDQpgYGB7cn0NCmRpYS51cmw8LSJodHRwczovL3d3dy5hbXN0YXQub3JnL3B1YmxpY2F0aW9ucy9qc2UvdjluMi80Y2RhdGEudHh0Ig0KZGlhbW9uZHMgPC1yZWFkLnRhYmxlKGRpYS51cmwpDQpuYW1lcyhkaWFtb25kcykgPC1jKCJDYXJhdCIsIkNvbG9yIiwiQ2xhcml0eSIsIkNlcnQiLCJQcmljZSIpDQpkaWFtb25kc1sxOjUsXQ0KYGBgDQpUbyBhZGQgdXAgdGhlIHRvdGFsIHZhbHVlIG9mIHRoZSBkaWFtb25kcyBwcmVzZW50IGZvciB0aGUgZnVsbCBkYXRhIHNldCBidXQgc2VwYXJhdGVkIGFjY29yZGluZyB0byBDb2xvciwgeW91IGNhbiB1c2UgVGFwcGx5IGxpa2UgdGhpczoNCg0KYGBge3J9DQp0YXBwbHkoZGlhbW9uZHMkUHJpY2UsSU5ERVg9ZGlhbW9uZHMkQ29sb3IsRlVOPXN1bSkNCiAgDQpgYGANCg0KDQpMYXBwbHkgaXMgc2ltaWxhciB0byBhcHBseSBidXQgYXBwbGllcyB0byBsaXN0cy4NCg0KYGBge3J9DQpiYXo8LWxpc3QoYWE9YygzLjQsMSksYmI9bWF0cml4KDE6NCwyLDIpLGNjPW1hdHJpeChjKFQsVCxGLFQsRixGKSwzLDIpLA0KICAgICAgICAgIGRkPSJzdHJpbmcgaGVyZSIsDQogICAgICAgICAgZWU9bWF0cml4KGMoInJlZCIsImJsdWUiLCJ5ZWxsb3ciKSkpDQpiYXoNCg0KYGBgDQoNCmBgYHtyfQ0KbGFwcGx5KGJheixGVU49aXMubWF0cml4KQ0KDQpgYGANClRoZSByZXR1cm5lZCB2YWx1ZSBpcyBhbHNvIGEgbGlzdCBidXQgaW4gYW4gYXJyYXkgZm9ybS4NClRvIHJldHVybiBhcyBhIHZlY3RvciwgdXNlIHRoZSBzYXBwbHkNCg0KYGBge3J9DQpzYXBwbHkoYmF6LEZVTj1pcy5tYXRyaXgpDQpgYGANCg0KWW91IGNhbiBwYXNzIGFkZGl0aW9uYWwgZnVuY3Rpb25zIHRvIHRoZSBhcHBseSBmdW5jdGlvbg0KDQpgYGB7cn0NCiMgYWRkZWQgc29ydGluZw0KZm9vDQphcHBseShmb28sMSxzb3J0LGRlY3JlYXNpbmc9VFJVRSkNCmBgYA0KDQoNCg0KPGgyPiAxMC4zIE90aGVyIENvbnRyb2wgRmxvdyBNZWNoYW5pc20gPC9oMj4NCjxoMz4gMTAuMy4xIERlY2xhcmluZyBCcmVhayBvciBuZXh0IDwvaDM+DQpUbyBwcmVtZXB0aXZlbHkgYnJlYWsgb3V0IG9mIGEgbG9vcCB5b3UgY2FuIGRlY2xhcmUgW2JyZWFrXQ0KDQpgYGB7cn0NCmZvbyA8LTUNCmJhciA8LWMoMiwzLDEuMSw0LDAsNC4xLDMpDQoNCmxvb3AxLnJlc3VsdDwtcmVwKE5BLGxlbmd0aChiYXIpKQ0KbG9vcDEucmVzdWx0DQoNCmZvcihpIGluIDE6bGVuZ3RoKGJhcikpew0KICB0ZW1wPC1mb28vYmFyW2ldDQogIGlmKGlzLmZpbml0ZSh0ZW1wKSl7DQogICAgbG9vcDEucmVzdWx0W2ldPC10ZW1wDQogIH0gZWxzZSB7DQogICAgYnJlYWsNCiAgfQ0KfQ0KbG9vcDEucmVzdWx0DQpgYGANClVzaW5nIGJyZWFrIGlzIGEgZHJhc3RpYyBzb2x1dGlvbiBtb3N0bHkgZm9yIHRyb3VibGVzaG9vdGluZy4gDQpZb3UgY2FuIHVzZSBbTmV4dF0NCg0KYGBge3J9DQpsb29wMi5yZXN1bHQ8LXJlcChOQSxsZW5ndGgoYmFyKSkNCmxvb3AyLnJlc3VsdA0KZm9yKGkgaW4gMTpsZW5ndGgoYmFyKSl7DQogIGlmKGJhcltpXT09MCl7DQogICAgbmV4dCgpDQogIH0NCmxvb3AyLnJlc3VsdFtpXTwtZm9vL2JhcltpXSANCn0NCmxvb3AyLnJlc3VsdA0KDQpgYGANCg0KPGgzPiAxMC4zLjIgVGhlIHJlcGVhdCBTdGF0ZW1lbnQgPC9oMz4NCkFub3RoZXIgd2F5IHRvIGRvIGFuIG9wZXJhdGlvbiBvdmVyIGFuZCBvdmVyIGFnYWluIGlzIHRvIHVzZSBbcmVwZWF0XQ0KVGhlIGdlbmVyYWwgZm9ybWF0Og0KDQpyZXBlYXR7DQpkbyBhbnkgY29kZSBoZXJlLg0KfQ0KDQoNCmBgYHtyfQ0KZmliLmEgPC0xDQpmaWIuYjwtMQ0KcmVwZWF0ew0KICB0ZW1wIDwtZmliLmErZmliLmINCiAgZmliLmE8LWZpYi5iDQogIGZpYi5iIDwtdGVtcA0KICBjYXQoZmliLmIsIiwgIixzZXA9IiAiKQ0KICBpZihmaWIuYj4xNTApew0KICAgIGNhdCgiYnJlYWtub3cuLlxuIikNCiAgICBicmVhaw0KICB9DQp9DQpgYGANCg0K