I would like to solve the challenge. The language of my preference is R. I am not sure how to receive input. On hackerrank coding window it says that
"# Enter your code here. Read input from STDIN. Print output to STDOUT"
So far I am used to receiving input by using
v1 <- readline("Enter two integers: ")
How should i receive input on hackerrank? I tried to see solved examples but couldn't find any solved examples.
update 1
Below code works in R. Only problem is number of steps and ball values are not provided from keyboard input. We have to update them manually on line 1 and line2. How could I get update below solution so that it works on hackerrank?
steps=4
ball_numbers=c(1,2,2,2)
d=as.data.frame(c(0,1))
for (i in (1:(length(ball_numbers)-1)))
{
assign(x = paste("A", i, sep = ""),value = c(0,1))
e <- as.data.frame(get(paste("A", i, sep = "")))
colnames(e) <- paste("A", i, sep="")
d <- merge(d,e)
}
d=as.matrix(t(d))
answer=sum(ball_numbers %*% d)/ncol(d)
update2
Below code produces correct answer
# Enter your code here. Read input from STDIN. Print output to STDOUT
nums <- read.table("/dev/stdin", sep=" ");
nums <- as.matrix(as.data.frame(t(nums)))
steps=nums[1]
ball_numbers=nums[2:length(nums)]
d=as.data.frame(c(0,1))
for (i in (1:(length(ball_numbers)-1)))
{
assign(paste("A", i, sep = ""),value = c(0,1))
e <- as.data.frame(get(paste("A", i, sep = "")))
colnames(e) <- paste("A", i, sep="")
d <- merge(d,e)
}
d=as.matrix(t(d))
#answer=as.numeric(format(round(sum(ball_numbers %*% d)/ncol(d),1),nsmall=1))
answer = print(format(sum(ball_numbers %*% d)/ncol(d),nsmall=1, digits = 1), quote = F)
write.table(as.numeric(answer), sep = "", append=T, row.names = F, col.names = F,quote = FALSE,)
I get below output
[1] 2.0
2
which is different from expected output which is below. How can i modify my code to get the correct format of output
2.0
Look at the "warmup".
data <- suppressWarnings(read.table("stdin", sep=" "));
Alternatively you can use
data <- suppressWarnings(readLines(file("stdin")))
Also Refer this page in hackerrank
I faced the similar issue for reading input in R in hackerrank . Then to use readLines i used following :
input<-file('stdin', 'r')
x <- readLines(input, n=1)
If u again want to read another data y use same approach :
y <- readLines(input, n=1)
#---this solves the problem
# Enter your code here. Read input from STDIN. Print output to STDOUT
nums <- suppressWarnings(readLines(file("stdin")))
#nums <- suppressWarnings(readLines(file("new.txt")))
nums <- as.matrix(as.data.frame(t(nums)))
class(nums) <- "numeric"
steps=nums[1]
ball_numbers=nums[2:length(nums)]
d=as.data.frame(c(0,1))
for (i in (1:(length(ball_numbers)-1)))
{
assign(paste("A", i, sep = ""),value = c(0,1))
e <- as.data.frame(get(paste("A", i, sep = "")))
colnames(e) <- paste("A", i, sep="")
d <- merge(d,e)
}
d=as.matrix(t(d))
answer=sum(ball_numbers %*% d)/ncol(d)
write.table(cat(format(answer, nsmall=1), sep="\n"), sep = "", append=T, row.names = F, col.names = F)
Another approach:
con = file('stdin', open ='r')
input = readLines(con)
z = c()
for(i in 2:length(input)){
z = c(z, as.numeric(input[[i]]))
}
cat(format(round(sum(z)/2, 1), nsmall = 1), sep = "\n")
A very handy one-liner to read in from standard input is the scan function, for instance:
text <- scan(file = 'stdin', what = 'character', sep = '\r')
Related
Hope you don't mind if this is too easy for you.
In R, I am using fromJSON() to read from 3 urls (tier 1 url) , in the JSON file there is "link" field which give me another url (tier 2 url) and I use that and read.table() to get my final data. My code now is like this:
# note, this code does not run
urlJohn <- www.foo1.com
urlJane <- www.foo2.com
urlJoe <- www.foo3.com
tempJohn <- fromJson(urlJohn)
tempJohn[["data"]][["rows"]]$link %<>%
{clean up this data}
dataJohn <- read.table(tempJohn[["data"]][["rows"]]$link,
header = TRUE,
sep = ",")
tempJane <- fromJson(urlJane)
tempJane[["data"]][["rows"]]$link %<>%
{clean up this data}
dataJane <- read.table(tempJane[["data"]][["rows"]]$link,
header = TRUE,
sep = ",")
tempJoe <- fromJson(urlJoe)
tempJoe[["data"]][["rows"]]$link %<>%
{clean up this data}
dataJoe <- read.table(tempJoe[["data"]][["rows"]]$link,
header = TRUE,
sep = ",")
As you can see, I am just copying-n-pasting code blocks. What I wish is this:
# note, this code also does not run
urlJohn <- www.foo1.com
urlJane <- www.foo2.com
urlJoe <- www.foo3.com
source <- c("John", "Jane", "joe")
for (i in source){
temp <- paste(temp, i, sep = "")
url <- paste(url, i, sep = "")
data <- paste(data, i, sep = "")
temp <- fromJson(url)
temp[["data"]][["rows"]]$link %<>%
{clean up this data}
data <- read.table(temp[["data"]][["rows"]]$link,
header = TRUE,
sep = ",")
}
What do I need to do to make the for loop work? If my question is not clear, please ask me to clarify it.
I usually find using lapply convenient than a for loop. Although you can easily convert this to a for loop if needed.
URLs <- c('www.foo1.com', 'www.foo2.com', 'www.foo3.com')
lapply(URLs, function(x) {
temp <- jsonlite::fromJSON(x)
temp[["data"]][["rows"]]$link %<>% {clean up this data}
read.table(temp[["data"]][["rows"]]$link,header = TRUE,sep = ",")
}) -> list_data
list_data
Thanks to #Ronak Shah. The R community strongly favors "non-For-loop" solution.
The way to get my desired result is lapply.
Below is non-running codes in mnemonics:
URLs <- c('www.foo1.com', 'www.foo2.com', 'www.foo3.com')
lapply(URLs, function(x) {
temp <- jsonlite::fromJSON(x)
x <- temp[["data"]][["rows"]]$link %<>% {clean up this data}
y <- read.table(temp[["data"]][["rows"]]$link,header = TRUE,sep = ",")
return(list(x, y))
})
And this is a running example.
x <- list(alpha = 1:10,
beta = exp(-3:3),
logic = c(TRUE,FALSE,FALSE,TRUE))
lapply(x, function(x){
temp <- sum(x) / 2
temp2 <- list(x,
temp)
return(temp2)
}
)
xlen <- 50 # Length
xGRU <- seq(1, 2723, by = xlen) # Start ID
xjob <- 36 # Numbe of Jobs per Joblist
# List of all run Commands
runcommands <- paste("TESTTHIS", xGRU, xlen , '-r d', '-m', sep=" ")
runcommands <- append(head(runcommands, -1),
paste("TESTTHIS", tail(xGRU,1), 11723%%xlen ,
'-r d', '-m', sep=" "))
for(i in seq(1, length(runcommands), by = xjob)){
jobfileName <- paste0('data_raw/joblist_', i, ".txt")
cat(paste(runcommands[i:(i+xjob-1)]), file=jobfileName, append=TRUE, sep = "\n")
}
But the last file that is created has NAs in it. How can I ensure that the for loop doesn't write out NA when the index runs out?
Use ?lapply and simply drop the NA objects from each vector prior to writing
lapply(seq_along(runcommands), function(i){
# create a new file inside of the temporary directory
# for help see ?sprintf
fl <- sprintf('data_raw/joblist_%s.txt', i)
# cleaned up your seq chunk a bit, and then the key is to remove
# the NA items prior to writing to file
job_list <- runcommands[seq(i, i + (xjob - 1))] %>% .[!is.na(.)]
stringi::stri_write_lines(job_list, sep = "\n", fname = fl)
})
You could prevent this from happening by being more rigorous with your use of indices in the cat function call. But as a quick workaround you can do this:
for(i in seq(1, length(runcommands), by = xjob)){
jobfileName <- paste0('~/SO_posts/joblist_', i, ".txt")
cat(paste(na.omit(runcommands[i:(i+xjob-1)])), file=jobfileName, append=TRUE, sep = "\n")
}
I'm a total R-newbie and I have a simple question which might be hilarious but I could not find a answer even though I searched for 4 hours. I might miss the concept.
I write a Monte-Carlo script with a lot of variables stored in differnet environments. At the end of every iteration I want to write all variables (the ones which are listed when typing ls()) to a table.
This would be a working example (without the item I ask for) of what I want to do. (Thank you for your help sofar, it helped me to build that example!)
#input data (data will be manipulated for mc later on)
ha<-5
w_eff<-1.9
v_T1<-8
n<-1000 #number of iterations
#function
T1_func <- function(ha_mc, w_eff_mc, v_T1_mc){
T1_result <- ((ha*10)/(w_eff*v_T1));
return(T1_result)
}
for(i in 1:n){ #number of iterations
#MC maipulation (illustrative)
ha_mc<-rnorm(1, ha, sd=1)
w_eff_mc<-rnorm(1, w_eff, sd=1)
v_T1_mc<-rnorm(1, v_T1, sd=1)
#calculation
T1_mc<-T1_func(ha_mc, w_eff_mc, v_T1_mc)
#now I want to write all variables to a table
df<-data.frame(ha, w_eff, v_T1, ha_mc, w_eff_mc, v_T1_mc, T1_mc)
write.table(df, file = "result.txt", append = TRUE, quote = TRUE, sep = " ",
eol = "\n", na = "NA", dec = ".", row.names = FALSE,
col.names = !file.exists("result.txt"), qmethod = c("escape", "double"))
}
My question would be: how do I get that:
df<-data.frame(ha, w_eff, v_T1, ha_mc, w_eff_mc, v_T1_mc, T1_mc)
without writing down all the variables (ha, w_eff, v_T1, ha_mc, w_eff_mc, v_T1_mc, T1_mc) but with something like "ls()". And how do I get that for the variables in the different environments so that I will have a column named "my.env$w_eff".
Thank you very much!
I woud suggest not using ls() and instead making a data.frame which contains the variables you want to store. Here I firstly create the file "results.txt" with the correct column headers (I'm storing values of a, b, and c) and then in each iteration I append the corresponding values to the file. Hope this helps:
n <- 10L
write.table(data.frame("a", "b", "c"), file = "result.txt",
col.names = FALSE, row.names = FALSE)
for (i in seq_len(n)) {
#do MC
a <- rnorm(1L)
b <- exp(a)
c <- a + b
write.table(data.frame(a, b, c), file = "result.txt",
append = TRUE, row.names = i, col.names = FALSE)
}
Thats the solution I found with your help, thx!
write_table_func <- function(env_name, file_part_name, dir_name){
#write input to table
df_input<-data.frame(as.list(get(env_name), all.names=TRUE))
sort.df_input <- df_input[,order(names(df_input))]
filename<-(paste(sep="", dir_name, "/", "tabl_", process_n, "_", process_step_n, file_part_name, ".txt"));
suppressWarnings(write.table(sort.df_input, file = paste(filename), append = TRUE, quote = TRUE, sep = " ",
eol = "\n", na = "NA", dec = ".", row.names = FALSE,
col.names = !file.exists(paste(filename)), qmethod = c("escape", "double")));
rm(df_input);
rm(sort.df_input);
}
Is there an R function for parsing INI like configuration files?
While searching I only found this discussion.
Here is an answer that was given to exact the same question on r-help in 2007 (thanks to #Spacedman for pointing this out):
Parse.INI <- function(INI.filename)
{
connection <- file(INI.filename)
Lines <- readLines(connection)
close(connection)
Lines <- chartr("[]", "==", Lines) # change section headers
connection <- textConnection(Lines)
d <- read.table(connection, as.is = TRUE, sep = "=", fill = TRUE)
close(connection)
L <- d$V1 == "" # location of section breaks
d <- subset(transform(d, V3 = V2[which(L)[cumsum(L)]])[1:3],
V1 != "")
ToParse <- paste("INI.list$", d$V3, "$", d$V1, " <- '",
d$V2, "'", sep="")
INI.list <- list()
eval(parse(text=ToParse))
return(INI.list)
}
Actually, I wrote a short and presumably buggy function (i.e. not covering all corner cases) which works for me now:
read.ini <- function(x) {
if(length(x)==1 && !any(grepl("\\n", x))) lines <- readLines(x) else lines <- x
lines <- strsplit(lines, "\n", fixed=TRUE)[[1]]
lines <- lines[!grepl("^;", lines) & nchar(lines) >= 2] # strip comments & blank lines
lines <- gsub("\\r$", "", lines)
idx <- which(grepl("^\\[.+\\]$", lines))
if(idx[[1]] != 1) stop("invalid INI file. Must start with a section.")
res <- list()
fun <- function(from, to) {
tups <- strsplit(lines[(from+1):(to-1)], "[ ]*=[ ]*")
for (i in 1:length(tups))
if(length(tups[[i]])>2) tups[[i]] <- c(tups[[i]][[1]], gsub("\\=", "=", paste(tail(tups[[i]],-1), collapse="=")))
tups <- unlist(tups)
keys <- strcap(tups[seq(from=1, by=2, length.out=length(tups)/2)])
vals <- tups[seq(from=2, by=2, length.out=length(tups)/2)]
sec <- strcap(substring(lines[[from]], 2, nchar(lines[[from]])-1))
res[[sec]] <<- setNames(vals, keys)
}
mapply(fun, idx, c(tail(idx, -1), length(lines)+1))
return(res)
}
where strcap is a helper function that capitalizes a string:
strcap <- function(s) paste(toupper(substr(s,1,1)), tolower(substring(s,2)), sep="")
There are also some C solutions for this, like inih or libini that might be useful. I did not try them out, though.
I can use write.table function to create an output data from a data.frame:
> write.table(head(cars), sep = "|", row.names=FALSE)
"speed"|"dist"
4|2
4|10
7|4
7|22
8|16
9|10
How can I create my own write.table function which creates an output like this (header with double pipes and data with preceding and succeeding pipes)?:
||"speed"||"dist"||
|4|2|
|4|10|
|7|4|
|7|22|
|8|16|
|9|10|
write.table can get you part of the way, but you will still need to do some fiddling around to get things to work just as you want.
Here's an example:
x <- capture.output(
write.table(head(cars), sep = "|", row.names = FALSE, eol = "|\n"))
x2 <- paste0("|", x)
x2[1] <- gsub("|", "||", x2[1], fixed=TRUE)
cat(x2, sep = "\n")
# ||"speed"||"dist"||
# |4|2|
# |4|10|
# |7|4|
# |7|22|
# |8|16|
# |9|10|
As a function, I guess in its most basic form it could look something like:
write.myOut <- function(inDF, outputFile) {
x <- capture.output(
write.table(inDF, sep = "|", row.names = FALSE, eol = "|\n"))
x <- paste0("|", x)
x[1] <- gsub("|", "||", x[1], fixed=TRUE)
cat(x, sep = "\n", file=outputFile)
}
I don't think that it is possible with write.table. Here is a workaround:
# function for formatting a row
rowFun <- function(x, sep = "|") {
paste0(sep, paste(x, collapse = sep), sep)
}
# create strings
rows <- apply(head(cars), 1, rowFun)
header <- rowFun(gsub("^|(.)$", "\\1\"", names(head(cars))), sep = "||")
# combine header and row strings
vec <- c(header, rows)
# write the vector
write(vec, sep = "\n", file = "myfile.sep")
The resulting file:
||"speed"||"dist"||
|4|2|
|4|10|
|7|4|
|7|22|
|8|16|
|9|10|