Initialisation

Configure evironment

rm(list = ls())
setwd("~/OneDrive/datasciencecoursera/R_Programming/week2")

The function ‘pollutantmean’ calculates the mean of a pollutant (sulfate or nitrate) across a specified list of monitors. The function ‘pollutantmean’ takes three arguments: ‘directory’, ‘pollutant’, and ‘id’. Given a vector monitor ID numbers, ‘pollutantmean’ reads that monitors’ particulate matter data from the directory specified in the ‘directory’ argument and returns the mean of the pollutant across all of the monitors, ignoring any missing values coded as NA.

pollutantmean <- function(directory, pollutant, id = 1:332) {
    ## 'directory' is a character vector of length 1 indicating
    ## the location of the CSV files
    
    ## 'pollutant' is a character vector of length 1 indicating
    ## the name of  the pollutant for which we will calcultate the
    ## mean; either "sulfate" or "nitrate"
    
    ## 'id' is an integer vector indicating the monitor ID numbers
    ## to be used
    
    ## Return the mean of the pollutant across all monitors list
    ## in the 'id' vector (ignoring NA values)
    ## NOTE: Do not round the result
    means <- c()
    
    for(monitor in id){
        path <- paste(getwd(), "/", directory, "/", sprintf("%03d", monitor), ".csv", sep = "")
        monitor_data <- read.csv(path)
        interested_data <- monitor_data[pollutant]
        means <- c(means, interested_data[!is.na(interested_data)])
    }
    
    mean(means)
}

The function ‘complete’ reads a directory full of files and reports the number of completely observed cases in each data file. The function should return a data frame where the first column is the name of the file and the second column is the number of complete cases.

complete <- function(directory, id = 1:332){
    ## 'director' is a character vector of length 1 indicating
    ## the location of the CSV files
    
    ## 'id' is an integer vector indicating the monitor ID numbers
    ## to be used
    
    ## Return a data frame of the from:
    ## id nobs
    ## 1  117
    ## 2  1041
    ## ...
    ## where 'id' is the monitor ID number and 'nobs' is the
    ## number of complete cases
    results <- data.frame(id=numeric(0), nobs=numeric(0))
    for(monitor in id){
        path <- paste(getwd(), "/", directory, "/", sprintf("%03d", monitor), ".csv", sep = "")
        monitor_data <- read.csv(path)
        interested_data <- monitor_data[(!is.na(monitor_data$sulfate)), ]
        interested_data <- interested_data[(!is.na(interested_data$nitrate)), ]
        nobs <- nrow(interested_data)
        results <- rbind(results, data.frame(id=monitor, nobs=nobs))
    }
    results
}

The function ‘corr’ takes a directory of data files and a threshold for complete cases and calculates the correlation between sulfate and nitrate for monitor locations where the number of completely observed cases (on all variables) is greater than the threshold. The function should return a vector of correlations for the monitors that meet the threshold requirement. If no monitors meet the threshold requirement, then the function should return a numeric vector of length 0.

corr <- function(directory, threshold = 0){
    ## 'directory' is a character vector of length 1 indicating
    ## the location of the CSV files
    
    ## 'threshold' is a numeric vector of length 1 indicating the 
    ## number of completely observed observations (on all
    ## variables) requi?red to compute the correlation between
    ## nitrate and sulfate; the default is 0
    
    ## Return a numeric vector of correlations
    ## NOTE: Do not round the result!
    cor_results <- numeric(0)
    
    complete_cases <- complete(directory)
    complete_cases <- complete_cases[complete_cases$nobs>=threshold, ]
    #print(complete_cases["id"])
    #print(unlist(complete_cases["id"]))
    #print(complete_cases$id)
    
    if(nrow(complete_cases)>0){
        for(monitor in complete_cases$id){
            path <- paste(getwd(), "/", directory, "/", sprintf("%03d", monitor), ".csv", sep = "")
            #print(path)
            monitor_data <- read.csv(path)
            #print(monitor_data)
            interested_data <- monitor_data[(!is.na(monitor_data$sulfate)), ]
            interested_data <- interested_data[(!is.na(interested_data$nitrate)), ]
            sulfate_data <- interested_data["sulfate"]
            nitrate_data <- interested_data["nitrate"]
            cor_results <- c(cor_results, cor(sulfate_data, nitrate_data))
        }
    }
    cor_results
}

Quiz

Q1. What value is returned by the following call to pollutantmean()? You should round your output to 3 digits.

pollutantmean("specdata", "sulfate", 1:10)
[1] 4.064128

Q2. What value is returned by the following call to pollutantmean()? You should round your output to 3 digits.

pollutantmean("specdata", "nitrate", 70:72)
[1] 1.706047

Q3. What value is returned by the following call to pollutantmean()? You should round your output to 3 digits.

pollutantmean("specdata", "sulfate", 34)
[1] 1.477143

Q4. What value is returned by the following call to pollutantmean()? You should round your output to 3 digits.

pollutantmean("specdata", "nitrate")
[1] 1.702932

Q5. What value is printed at end of the following code?

cc <- complete("specdata", c(6, 10, 20, 34, 100, 200, 310))
print(cc$nobs)
[1] 228 148 124 165 104 460 232

Q6. What value is printed at end of the following code?

cc <- complete("specdata", 54)
print(cc$nobs)
[1] 219

Q7. What value is printed at end of the following code?

set.seed(42)
cc <- complete("specdata", 332:1)
use <- sample(332, 10)
print(cc[use, "nobs"])
 [1] 711 135  74 445 178  73  49   0 687 237

Q8. What value is printed at end of the following code?

cr <- corr("specdata")                
cr <- sort(cr)                
set.seed(868)                
out <- round(cr[sample(length(cr), 5)], 4)
print(out)
[1]  0.2688  0.1127 -0.0085  0.4586  0.0447

Q9. What value is printed at end of the following code?

cr <- corr("specdata", 129)                
cr <- sort(cr)                
n <- length(cr)                
set.seed(197)                
out <- c(n, round(cr[sample(n, 5)], 4))
print(out)
[1] 243.0000   0.2540   0.0504  -0.1462  -0.1680   0.5969

Q10. What value is printed at end of the following code?

cr <- corr("specdata", 2000)                
n <- length(cr)                
cr <- corr("specdata", 1000)                
cr <- sort(cr)
print(c(n, round(cr, 4)))
[1]  0.0000 -0.0190  0.0419  0.1901
LS0tCnRpdGxlOiAiUiBQcm9ncmFtbWluZyBXZWVrIDI6IEFzc2lnbm1lbnQgMSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyNJbml0aWFsaXNhdGlvbgpDb25maWd1cmUgZXZpcm9ubWVudApgYGB7cn0Kcm0obGlzdCA9IGxzKCkpCnNldHdkKCJ+L09uZURyaXZlL2RhdGFzY2llbmNlY291cnNlcmEvUl9Qcm9ncmFtbWluZy93ZWVrMiIpCmBgYApUaGUgZnVuY3Rpb24gJ3BvbGx1dGFudG1lYW4nIGNhbGN1bGF0ZXMgdGhlIG1lYW4gb2YgYSBwb2xsdXRhbnQgKHN1bGZhdGUgb3Igbml0cmF0ZSkgYWNyb3NzIGEgc3BlY2lmaWVkIGxpc3Qgb2YgbW9uaXRvcnMuIFRoZSBmdW5jdGlvbiAncG9sbHV0YW50bWVhbicgdGFrZXMgdGhyZWUgYXJndW1lbnRzOiAnZGlyZWN0b3J5JywgJ3BvbGx1dGFudCcsIGFuZCAnaWQnLiBHaXZlbiBhIHZlY3RvciBtb25pdG9yIElEIG51bWJlcnMsICdwb2xsdXRhbnRtZWFuJyByZWFkcyB0aGF0IG1vbml0b3JzJyBwYXJ0aWN1bGF0ZSBtYXR0ZXIgZGF0YSBmcm9tIHRoZSBkaXJlY3Rvcnkgc3BlY2lmaWVkIGluIHRoZSAnZGlyZWN0b3J5JyBhcmd1bWVudCBhbmQgcmV0dXJucyB0aGUgbWVhbiBvZiB0aGUgcG9sbHV0YW50IGFjcm9zcyBhbGwgb2YgdGhlIG1vbml0b3JzLCBpZ25vcmluZyBhbnkgbWlzc2luZyB2YWx1ZXMgY29kZWQgYXMgTkEuCmBgYHtyfQpwb2xsdXRhbnRtZWFuIDwtIGZ1bmN0aW9uKGRpcmVjdG9yeSwgcG9sbHV0YW50LCBpZCA9IDE6MzMyKSB7CiAgICAjIyAnZGlyZWN0b3J5JyBpcyBhIGNoYXJhY3RlciB2ZWN0b3Igb2YgbGVuZ3RoIDEgaW5kaWNhdGluZwogICAgIyMgdGhlIGxvY2F0aW9uIG9mIHRoZSBDU1YgZmlsZXMKICAgIAogICAgIyMgJ3BvbGx1dGFudCcgaXMgYSBjaGFyYWN0ZXIgdmVjdG9yIG9mIGxlbmd0aCAxIGluZGljYXRpbmcKICAgICMjIHRoZSBuYW1lIG9mICB0aGUgcG9sbHV0YW50IGZvciB3aGljaCB3ZSB3aWxsIGNhbGN1bHRhdGUgdGhlCiAgICAjIyBtZWFuOyBlaXRoZXIgInN1bGZhdGUiIG9yICJuaXRyYXRlIgogICAgCiAgICAjIyAnaWQnIGlzIGFuIGludGVnZXIgdmVjdG9yIGluZGljYXRpbmcgdGhlIG1vbml0b3IgSUQgbnVtYmVycwogICAgIyMgdG8gYmUgdXNlZAogICAgCiAgICAjIyBSZXR1cm4gdGhlIG1lYW4gb2YgdGhlIHBvbGx1dGFudCBhY3Jvc3MgYWxsIG1vbml0b3JzIGxpc3QKICAgICMjIGluIHRoZSAnaWQnIHZlY3RvciAoaWdub3JpbmcgTkEgdmFsdWVzKQogICAgIyMgTk9URTogRG8gbm90IHJvdW5kIHRoZSByZXN1bHQKICAgIG1lYW5zIDwtIGMoKQogICAgCiAgICBmb3IobW9uaXRvciBpbiBpZCl7CiAgICAgICAgcGF0aCA8LSBwYXN0ZShnZXR3ZCgpLCAiLyIsIGRpcmVjdG9yeSwgIi8iLCBzcHJpbnRmKCIlMDNkIiwgbW9uaXRvciksICIuY3N2Iiwgc2VwID0gIiIpCiAgICAgICAgbW9uaXRvcl9kYXRhIDwtIHJlYWQuY3N2KHBhdGgpCiAgICAgICAgaW50ZXJlc3RlZF9kYXRhIDwtIG1vbml0b3JfZGF0YVtwb2xsdXRhbnRdCiAgICAgICAgbWVhbnMgPC0gYyhtZWFucywgaW50ZXJlc3RlZF9kYXRhWyFpcy5uYShpbnRlcmVzdGVkX2RhdGEpXSkKICAgIH0KICAgIAogICAgbWVhbihtZWFucykKfQpgYGAKVGhlIGZ1bmN0aW9uICdjb21wbGV0ZScgcmVhZHMgYSBkaXJlY3RvcnkgZnVsbCBvZiBmaWxlcyBhbmQgcmVwb3J0cyB0aGUgbnVtYmVyIG9mIGNvbXBsZXRlbHkgb2JzZXJ2ZWQgY2FzZXMgaW4gZWFjaCBkYXRhIGZpbGUuIFRoZSBmdW5jdGlvbiBzaG91bGQgcmV0dXJuIGEgZGF0YSBmcmFtZSB3aGVyZSB0aGUgZmlyc3QgY29sdW1uIGlzIHRoZSBuYW1lIG9mIHRoZSBmaWxlIGFuZCB0aGUgc2Vjb25kIGNvbHVtbiBpcyB0aGUgbnVtYmVyIG9mIGNvbXBsZXRlIGNhc2VzLiAKYGBge3J9CmNvbXBsZXRlIDwtIGZ1bmN0aW9uKGRpcmVjdG9yeSwgaWQgPSAxOjMzMil7CiAgICAjIyAnZGlyZWN0b3InIGlzIGEgY2hhcmFjdGVyIHZlY3RvciBvZiBsZW5ndGggMSBpbmRpY2F0aW5nCiAgICAjIyB0aGUgbG9jYXRpb24gb2YgdGhlIENTViBmaWxlcwogICAgCiAgICAjIyAnaWQnIGlzIGFuIGludGVnZXIgdmVjdG9yIGluZGljYXRpbmcgdGhlIG1vbml0b3IgSUQgbnVtYmVycwogICAgIyMgdG8gYmUgdXNlZAogICAgCiAgICAjIyBSZXR1cm4gYSBkYXRhIGZyYW1lIG9mIHRoZSBmcm9tOgogICAgIyMgaWQgbm9icwogICAgIyMgMSAgMTE3CiAgICAjIyAyICAxMDQxCiAgICAjIyAuLi4KICAgICMjIHdoZXJlICdpZCcgaXMgdGhlIG1vbml0b3IgSUQgbnVtYmVyIGFuZCAnbm9icycgaXMgdGhlCiAgICAjIyBudW1iZXIgb2YgY29tcGxldGUgY2FzZXMKICAgIHJlc3VsdHMgPC0gZGF0YS5mcmFtZShpZD1udW1lcmljKDApLCBub2JzPW51bWVyaWMoMCkpCiAgICBmb3IobW9uaXRvciBpbiBpZCl7CiAgICAgICAgcGF0aCA8LSBwYXN0ZShnZXR3ZCgpLCAiLyIsIGRpcmVjdG9yeSwgIi8iLCBzcHJpbnRmKCIlMDNkIiwgbW9uaXRvciksICIuY3N2Iiwgc2VwID0gIiIpCiAgICAgICAgbW9uaXRvcl9kYXRhIDwtIHJlYWQuY3N2KHBhdGgpCiAgICAgICAgaW50ZXJlc3RlZF9kYXRhIDwtIG1vbml0b3JfZGF0YVsoIWlzLm5hKG1vbml0b3JfZGF0YSRzdWxmYXRlKSksIF0KICAgICAgICBpbnRlcmVzdGVkX2RhdGEgPC0gaW50ZXJlc3RlZF9kYXRhWyghaXMubmEoaW50ZXJlc3RlZF9kYXRhJG5pdHJhdGUpKSwgXQogICAgICAgIG5vYnMgPC0gbnJvdyhpbnRlcmVzdGVkX2RhdGEpCiAgICAgICAgcmVzdWx0cyA8LSByYmluZChyZXN1bHRzLCBkYXRhLmZyYW1lKGlkPW1vbml0b3IsIG5vYnM9bm9icykpCiAgICB9CiAgICByZXN1bHRzCn0KYGBgClRoZSBmdW5jdGlvbiAnY29ycicgdGFrZXMgYSBkaXJlY3Rvcnkgb2YgZGF0YSBmaWxlcyBhbmQgYSB0aHJlc2hvbGQgZm9yIGNvbXBsZXRlIGNhc2VzIGFuZCBjYWxjdWxhdGVzIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHN1bGZhdGUgYW5kIG5pdHJhdGUgZm9yIG1vbml0b3IgbG9jYXRpb25zIHdoZXJlIHRoZSBudW1iZXIgb2YgY29tcGxldGVseSBvYnNlcnZlZCBjYXNlcyAob24gYWxsIHZhcmlhYmxlcykgaXMgZ3JlYXRlciB0aGFuIHRoZSB0aHJlc2hvbGQuIFRoZSBmdW5jdGlvbiBzaG91bGQgcmV0dXJuIGEgdmVjdG9yIG9mIGNvcnJlbGF0aW9ucyBmb3IgdGhlIG1vbml0b3JzIHRoYXQgbWVldCB0aGUgdGhyZXNob2xkIHJlcXVpcmVtZW50LiBJZiBubyBtb25pdG9ycyBtZWV0IHRoZSB0aHJlc2hvbGQgcmVxdWlyZW1lbnQsIHRoZW4gdGhlIGZ1bmN0aW9uIHNob3VsZCByZXR1cm4gYSBudW1lcmljIHZlY3RvciBvZiBsZW5ndGggMC4KYGBge3J9CmNvcnIgPC0gZnVuY3Rpb24oZGlyZWN0b3J5LCB0aHJlc2hvbGQgPSAwKXsKICAgICMjICdkaXJlY3RvcnknIGlzIGEgY2hhcmFjdGVyIHZlY3RvciBvZiBsZW5ndGggMSBpbmRpY2F0aW5nCiAgICAjIyB0aGUgbG9jYXRpb24gb2YgdGhlIENTViBmaWxlcwogICAgCiAgICAjIyAndGhyZXNob2xkJyBpcyBhIG51bWVyaWMgdmVjdG9yIG9mIGxlbmd0aCAxIGluZGljYXRpbmcgdGhlIAogICAgIyMgbnVtYmVyIG9mIGNvbXBsZXRlbHkgb2JzZXJ2ZWQgb2JzZXJ2YXRpb25zIChvbiBhbGwKICAgICMjIHZhcmlhYmxlcykgcmVxdWk/cmVkIHRvIGNvbXB1dGUgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4KICAgICMjIG5pdHJhdGUgYW5kIHN1bGZhdGU7IHRoZSBkZWZhdWx0IGlzIDAKICAgIAogICAgIyMgUmV0dXJuIGEgbnVtZXJpYyB2ZWN0b3Igb2YgY29ycmVsYXRpb25zCiAgICAjIyBOT1RFOiBEbyBub3Qgcm91bmQgdGhlIHJlc3VsdCEKICAgIGNvcl9yZXN1bHRzIDwtIG51bWVyaWMoMCkKICAgIAogICAgY29tcGxldGVfY2FzZXMgPC0gY29tcGxldGUoZGlyZWN0b3J5KQogICAgY29tcGxldGVfY2FzZXMgPC0gY29tcGxldGVfY2FzZXNbY29tcGxldGVfY2FzZXMkbm9icz49dGhyZXNob2xkLCBdCiAgICAKICAgIGlmKG5yb3coY29tcGxldGVfY2FzZXMpPjApewogICAgICAgIGZvcihtb25pdG9yIGluIGNvbXBsZXRlX2Nhc2VzJGlkKXsKICAgICAgICAgICAgcGF0aCA8LSBwYXN0ZShnZXR3ZCgpLCAiLyIsIGRpcmVjdG9yeSwgIi8iLCBzcHJpbnRmKCIlMDNkIiwgbW9uaXRvciksICIuY3N2Iiwgc2VwID0gIiIpCiAgICAgICAgICAgICNwcmludChwYXRoKQogICAgICAgICAgICBtb25pdG9yX2RhdGEgPC0gcmVhZC5jc3YocGF0aCkKICAgICAgICAgICAgI3ByaW50KG1vbml0b3JfZGF0YSkKICAgICAgICAgICAgaW50ZXJlc3RlZF9kYXRhIDwtIG1vbml0b3JfZGF0YVsoIWlzLm5hKG1vbml0b3JfZGF0YSRzdWxmYXRlKSksIF0KICAgICAgICAgICAgaW50ZXJlc3RlZF9kYXRhIDwtIGludGVyZXN0ZWRfZGF0YVsoIWlzLm5hKGludGVyZXN0ZWRfZGF0YSRuaXRyYXRlKSksIF0KICAgICAgICAgICAgc3VsZmF0ZV9kYXRhIDwtIGludGVyZXN0ZWRfZGF0YVsic3VsZmF0ZSJdCiAgICAgICAgICAgIG5pdHJhdGVfZGF0YSA8LSBpbnRlcmVzdGVkX2RhdGFbIm5pdHJhdGUiXQogICAgICAgICAgICBjb3JfcmVzdWx0cyA8LSBjKGNvcl9yZXN1bHRzLCBjb3Ioc3VsZmF0ZV9kYXRhLCBuaXRyYXRlX2RhdGEpKQogICAgICAgIH0KICAgIH0KICAgIGNvcl9yZXN1bHRzCn0KYGBgCiMjUXVpegpRMS4gV2hhdCB2YWx1ZSBpcyByZXR1cm5lZCBieSB0aGUgZm9sbG93aW5nIGNhbGwgdG8gcG9sbHV0YW50bWVhbigpPyBZb3Ugc2hvdWxkIHJvdW5kIHlvdXIgb3V0cHV0IHRvIDMgZGlnaXRzLgpgYGB7cn0KcG9sbHV0YW50bWVhbigic3BlY2RhdGEiLCAic3VsZmF0ZSIsIDE6MTApCmBgYApRMi4gV2hhdCB2YWx1ZSBpcyByZXR1cm5lZCBieSB0aGUgZm9sbG93aW5nIGNhbGwgdG8gcG9sbHV0YW50bWVhbigpPyBZb3Ugc2hvdWxkIHJvdW5kIHlvdXIgb3V0cHV0IHRvIDMgZGlnaXRzLgpgYGB7cn0KcG9sbHV0YW50bWVhbigic3BlY2RhdGEiLCAibml0cmF0ZSIsIDcwOjcyKQpgYGAKUTMuIFdoYXQgdmFsdWUgaXMgcmV0dXJuZWQgYnkgdGhlIGZvbGxvd2luZyBjYWxsIHRvIHBvbGx1dGFudG1lYW4oKT8gWW91IHNob3VsZCByb3VuZCB5b3VyIG91dHB1dCB0byAzIGRpZ2l0cy4KYGBge3J9CnBvbGx1dGFudG1lYW4oInNwZWNkYXRhIiwgInN1bGZhdGUiLCAzNCkKYGBgClE0LiBXaGF0IHZhbHVlIGlzIHJldHVybmVkIGJ5IHRoZSBmb2xsb3dpbmcgY2FsbCB0byBwb2xsdXRhbnRtZWFuKCk/IFlvdSBzaG91bGQgcm91bmQgeW91ciBvdXRwdXQgdG8gMyBkaWdpdHMuCmBgYHtyfQpwb2xsdXRhbnRtZWFuKCJzcGVjZGF0YSIsICJuaXRyYXRlIikKYGBgClE1LiBXaGF0IHZhbHVlIGlzIHByaW50ZWQgYXQgZW5kIG9mIHRoZSBmb2xsb3dpbmcgY29kZT8KYGBge3J9CmNjIDwtIGNvbXBsZXRlKCJzcGVjZGF0YSIsIGMoNiwgMTAsIDIwLCAzNCwgMTAwLCAyMDAsIDMxMCkpCnByaW50KGNjJG5vYnMpCmBgYApRNi4gV2hhdCB2YWx1ZSBpcyBwcmludGVkIGF0IGVuZCBvZiB0aGUgZm9sbG93aW5nIGNvZGU/CmBgYHtyfQpjYyA8LSBjb21wbGV0ZSgic3BlY2RhdGEiLCA1NCkKcHJpbnQoY2Mkbm9icykKYGBgClE3LiBXaGF0IHZhbHVlIGlzIHByaW50ZWQgYXQgZW5kIG9mIHRoZSBmb2xsb3dpbmcgY29kZT8KYGBge3J9CnNldC5zZWVkKDQyKQpjYyA8LSBjb21wbGV0ZSgic3BlY2RhdGEiLCAzMzI6MSkKdXNlIDwtIHNhbXBsZSgzMzIsIDEwKQpwcmludChjY1t1c2UsICJub2JzIl0pCmBgYApROC4gV2hhdCB2YWx1ZSBpcyBwcmludGVkIGF0IGVuZCBvZiB0aGUgZm9sbG93aW5nIGNvZGU/CmBgYHtyfQpjciA8LSBjb3JyKCJzcGVjZGF0YSIpICAgICAgICAgICAgICAgIApjciA8LSBzb3J0KGNyKSAgICAgICAgICAgICAgICAKc2V0LnNlZWQoODY4KSAgICAgICAgICAgICAgICAKb3V0IDwtIHJvdW5kKGNyW3NhbXBsZShsZW5ndGgoY3IpLCA1KV0sIDQpCnByaW50KG91dCkKYGBgClE5LiBXaGF0IHZhbHVlIGlzIHByaW50ZWQgYXQgZW5kIG9mIHRoZSBmb2xsb3dpbmcgY29kZT8KYGBge3J9CmNyIDwtIGNvcnIoInNwZWNkYXRhIiwgMTI5KSAgICAgICAgICAgICAgICAKY3IgPC0gc29ydChjcikgICAgICAgICAgICAgICAgCm4gPC0gbGVuZ3RoKGNyKSAgICAgICAgICAgICAgICAKc2V0LnNlZWQoMTk3KSAgICAgICAgICAgICAgICAKb3V0IDwtIGMobiwgcm91bmQoY3Jbc2FtcGxlKG4sIDUpXSwgNCkpCnByaW50KG91dCkKYGBgClExMC4gV2hhdCB2YWx1ZSBpcyBwcmludGVkIGF0IGVuZCBvZiB0aGUgZm9sbG93aW5nIGNvZGU/CmBgYHtyfQpjciA8LSBjb3JyKCJzcGVjZGF0YSIsIDIwMDApICAgICAgICAgICAgICAgIApuIDwtIGxlbmd0aChjcikgICAgICAgICAgICAgICAgCmNyIDwtIGNvcnIoInNwZWNkYXRhIiwgMTAwMCkgICAgICAgICAgICAgICAgCmNyIDwtIHNvcnQoY3IpCnByaW50KGMobiwgcm91bmQoY3IsIDQpKSkKYGBgCg==