Skip to content

Reference Implementations

mert tiftikci edited this page Nov 24, 2020 · 1 revision

Reference implementations can be considered as addon to the quiz_checker_env script. For every question, a reference implementation should be written which specifies the tests, creates and dumps answer lists, and provide paths to its caller. Here an example reference implementation(actually used) will be broken down into its major parts and will be explained.

Accepting Arguments and Creating Dump Location

Keeping this section as is and changing variables sect_count and q_count variables are enough to populate file_names variables with dump paths with correct naming and placement conventions. When there is only one section, this part should be updated slightly.

args <- commandArgs(trailingOnly=TRUE)

sect_count <- 2
q_count <- 3
template <- paste(rep("io/in_%s_sect0", sect_count), 1:sect_count, sep="")
template <- paste(c(sapply(paste(template, "_q0", sep=""), rep, q_count)), rep(1:q_count, sect_count), ".RData", sep="")
file_names <- sapply(template, sprintf, args[1], USE.NAMES = F)

Defining Helper Functions for Solutions

Since handle_submissions can be called multiple times in testing, initial check controls if this script is run before to generate answer lists. The beginning of the answer sheet could be used for helper functions and parameters such as static file names, generator functions that can generate various test inputs in the correct format.

# check for existence of files and if exists, return them to caller
if(!all(sapply(file_names, file.exists))) {
  ###
  # This section has to be filled with the given naming convention
  ###
  
  generator1 <- function(seed=30, len=5, siz=20) {
    RNGversion("3.3.1")
    set.seed(seed)
    
    probs <- sample(c(0, rep(1, len - 1)))
    levels <- sample(letters, len)
    vec <- sample(levels, siz, replace = T, prob = probs)
    
    return(list(vec=vec, levs=levels))
  }
  
  generator2 <- function(seed=1, len=5, siz=20) {
    RNGversion("3.3.1")
    set.seed(seed)
    levels <- sample(letters, len)
    fact <- factor(sample(levels, siz, replace = T), levels = levels)
    
    return(list(fact=fact, lev=sample(levels, 1)))
  }
  
  generator3 <- function(seed=1, c=20, m=2, d=4, l=5, is_s1=T) {
    RNGversion("3.3.1")
    set.seed(seed)
    
    rates <- rnorm(c, m, d)
    
    brks <- NULL
    if(is_s1) {
      brks <- quantile(rates, seq(0, 1, len = l))
      brks[length(brks)] <- Inf
      brks[1] <- -Inf
      labs <- letters[1:(length(brks)-1)]
    } else {
      labs <- if(l%%3==0) {
        c("small", "large")
      } else if(l%%3==1) {
        c("low", "medium", "high")
      } else {
        c("poor", "fair", "good", "very good", "excellent")
      }
    }
    
    params <- list(values=rates, breaks=brks, labels=labs)
    if(!is_s1) names(params)[3] <- 'lab'
    
    return(params)
  }

Answers with Test Values

This section contains actual answers which could be shared with the students. True answers will be used in the test cases to generate expected results to save in answer lists.

  # Section 1
  
  # Q1
  
  getc <- function(vec, levs)
  {
    fact <- factor(vec, levels = levs)
    table(fact)
  }
  
  s1q1_1 <- generator1()
  s1q1_2 <- generator1(50)
  s1q1_3 <- generator1(70, 8)
  s1q1_4 <- generator1(90, 11, 50)
  
  # Q2
  
  getn <- function(fact, lev)
  {
    fact2 <- factor(fact, ordered = T)
    sum(fact2 >= lev)
  }
  
  s1q2_1 <- generator2()
  s1q2_2 <- generator2(50)
  s1q2_3 <- generator2(70, 8)
  s1q2_4 <- generator2(90, 11, 50)
  
  # Q3
  
  splitf <- function(values, breaks, labels)
  {
    split(values, cut(values, breaks = breaks, labels = labels))
  }
  
  s1q3_1 <- generator3()
  s1q3_2 <- generator3(50, 10, l = 4)
  s1q3_3 <- generator3(70, 30, 4, 8, 6)
  s1q3_4 <- generator3(90, 80, 8, 6, 10)
  
  # Section 2
  
  # Q1
  
  generator4 <- function(seed=30, len=5, siz=20) {
    RNGversion("3.3.1")
    set.seed(seed)
    
    lvls <- sample(letters, len+1)
    fact <- factor(sample(lvls[-len-1], siz, replace = T), levels = lvls[-len-1])
    
    return(list(fact=fact, new=lvls[len+1]))
  }
  
  addlevel <- function(fact, new)
  {
    levels(fact) <- c(levels(fact), new)
    fact
  }
  
  s2q1_1 <- generator4()
  s2q1_2 <- generator4(50)
  s2q1_3 <- generator4(70, 8)
  s2q1_4 <- generator4(90, 11, 50)
  
  # Q2
  
  getmax <- function(fact)
  {
    fact2 <- factor(fact, ordered = T)
    sum(fact2 == max(fact2))
  }
  
  s2q2_1 <- generator2()[-2]
  s2q2_2 <- generator2(50)[-2]
  s2q2_3 <- generator2(70, 8)[-2]
  s2q2_4 <- generator2(90, 11, 50)[-2]
  
  # Q3
  
  tof <- function(values, lab)
  {
    cats <- cut(values,
                breaks = length(lab),
                labels = lab)
    
    data.frame(values, cats)
  }
  
  s2q3_1 <- generator3(l = 0, is_s1 = F)[-2]
  s2q3_2 <- generator3(50, 10, l = 1, is_s1 = F)[-2]
  s2q3_3 <- generator3(70, 30, 4, 8, l = 2, is_s1 = F)[-2]
  s2q3_4 <- generator3(90, 80, 8, 6, l = 3, is_s1 = F)[-2]

Creating Answer Lists

After having the inputs and correct answers, here reference implementation is followed by answer lists creation. The format of these lists is explained in Quiz Checker. The loaders list is created in the last line which is needed even when no loader exists.

  ### Section1
  
  answers_sect1_q1 = list(
    "FNC__getc"=list(s1q1_1, do.call("getc", s1q1_1)),
    "FNC__getc"=list(s1q1_2, do.call("getc", s1q1_2)),
    "FNC__getc"=list(s1q1_3, do.call("getc", s1q1_3)),
    "FNC__getc"=list(s1q1_4, do.call("getc", s1q1_4))
  )
  
  answers_sect1_q2 = list(
    "FNC__getn"=list(s1q2_1, list(getn1=as.numeric(do.call("getn", s1q2_1)),
                                  getn2=do.call("getn", s1q2_1))),
    "FNC__getn"=list(s1q2_2, list(getn1=as.numeric(do.call("getn", s1q2_2)),
                                  getn2=do.call("getn", s1q2_2))),
    "FNC__getn"=list(s1q2_3, list(getn1=as.numeric(do.call("getn", s1q2_3)),
                                  getn2=do.call("getn", s1q2_3))),
    "FNC__getn"=list(s1q2_4, list(getn1=as.numeric(do.call("getn", s1q2_4)),
                                  getn2=do.call("getn", s1q2_4)))
  )
  
  answers_sect1_q3 = list(
    "FNC__splitf"=list(s1q3_1, do.call("splitf", s1q3_1)),
    "FNC__splitf"=list(s1q3_2, do.call("splitf", s1q3_2)),
    "FNC__splitf"=list(s1q3_3, do.call("splitf", s1q3_3)),
    "FNC__splitf"=list(s1q3_4, do.call("splitf", s1q3_4))
  )
  
  ### Section2
  
  answers_sect2_q1 = list(
    "FNC__addlevel"=list(s2q1_1, do.call("addlevel", s2q1_1)),
    "FNC__addlevel"=list(s2q1_2, do.call("addlevel", s2q1_2)),
    "FNC__addlevel"=list(s2q1_3, do.call("addlevel", s2q1_3)),
    "FNC__addlevel"=list(s2q1_4, do.call("addlevel", s2q1_4))
  )
  
  answers_sect2_q2 = list(
    "FNC__getmax"=list(s2q2_1, do.call("getmax", s2q2_1)),
    "FNC__getmax"=list(s2q2_2, do.call("getmax", s2q2_2)),
    "FNC__getmax"=list(s2q2_3, do.call("getmax", s2q2_3)),
    "FNC__getmax"=list(s2q2_4, do.call("getmax", s2q2_4))
  )
  
  answers_sect2_q3 = list(
    "FNC__tof"=list(s2q3_1, do.call("tof", s2q3_1)),
    "FNC__tof"=list(s2q3_2, do.call("tof", s2q3_2)),
    "FNC__tof"=list(s2q3_3, do.call("tof", s2q3_3)),
    "FNC__tof"=list(s2q3_4, do.call("tof", s2q3_4))
  )
  
  answers <- list(
    answers_sect1_q1, answers_sect1_q2, answers_sect1_q3,
    answers_sect2_q1, answers_sect2_q2, answers_sect2_q3
  )

  loaders <- c(NA, NA, NA, NA, NA, NA)

Dumping Answer Lists

This section can be used as-is as long as variables used here do exist with correct form as shown in this implementation.

  ###
  # Fill up until this part and do not change the rest
  ###
  
  path_trim <- function(path) { substr(path, 4, nchar(path)-6) }
  var_names <- sapply(file_names, path_trim, USE.NAMES = F)

  for(i in 1:length(var_names)) {
    assign(var_names[i], answers[[i]])
    if(!is.na(loaders[i])) {
      assign("loader", loaders[i])
      save(list = c("loader", var_names[i]), file = file_names[i])
    } else {
      save(list = var_names[i], file = file_names[i])
    }
  }
}

Returning Answer List Paths

After answer lists along with loaders are saved, file paths are returned to the caller.

This section can be used as-is as long as variables used here do exist with correct form as shown in this implementation.

# return filenames to caller
garb <- sapply(file_names, cat, "\n", sep="")

Clone this wiki locally