overview

After writing your four versions of the Factorial function, use the microbenchmark package to time the operation of these functions and provide a summary of their performance. In addition to timing your functions for specific inputs, make sure to show a range of inputs in order to demonstrate the timing of each function for larger inputs.

1. Factorial_loop: Computes the factorial of an integer using looping.

fac_loop <- function(n){
  stopifnot(n>=0)
  if (n == 0){
    return(1)
  }
  else {
    res <- 1
    for (i in 1:n){
      res <- res * i
    }
    return(res)
  }
}
fac_loop(4)
[1] 24

2. Factorial_reduce: Computes the factorial using the reduce().

fac_Reduce <- function(n){
  stopifnot(n>=0)
  # because factoriel(0)=1, it's important to make condition
  if (n==0){
    return(1)
  }
  else {
    reduce(1:n, function(x,y){
      x*y
    })
  }
}
fac_Reduce(4)
[1] 24

3. Factorial_func: Uses recursion to compute the factorial.

fac_Recursion <- function(n){
  stopifnot(n>=0)
  if (n==0){
    return(1)
  }
  else {
    return(n*fac_Recursion(n-1))
  }
}
fac_Recursion(4)
[1] 24

4. Factorial_mem: Uses memorization to compute the factorial.

fac_table <- c(1)
fac_Mem <- function(n){
  # Because factorial of negatif number does not exist we stop if n<0
  stopifnot(n>=0)
  if (n==0){
    return(1)
  }
  else {
    if (!is.na(fac_table[n])){
      return(fac_table[n])
    } else {
      fac_table[n-1] <<- fac_Mem(n-1)
      return(n*fac_table[n-1])
    }
  }
  
}
fac_Mem(4)
[1] 24

5. use the microbenchmark package:

to time the operation of these functions and provide a summary of their performance.In addition to timing your functions for specific inputs, make sure to show a range of inputs in order to demonstrate the timing of each function for larger inputs.

the function below “compare_time” is intuitive. Given n it print a dataframe where we can see the summary of 100 time of computing of facotrial(n) using the 4 differents technique. And by looking the result we can get insight about the time consuming of differents techniques.

compare_time <- function(n){
  as.data.frame(summary(microbenchmark(fac_loop(n), 
                                       fac_Mem(n),
                                       fac_Recursion(n),
                                       fac_Reduce(n))))
}

range_time() function below takes a given factorial function and a range of integer (n_min:n_max), then computes the median times of 100 computing of each integer with the given factorial function.

range_time <- function(f, n_min = 1, n_max = 10){
  df_func <- map(seq(n_min, n_max), function(x){microbenchmark(f(x))$time})
  names(df_func) <- paste0("X",".", n_min:n_max)
  df_func <- as.data.frame(df_func)
  df_func %<>%
    gather(num, time) %>%
    group_by(num) %>%
    summarise(med_time = median(time))
  return(df_func)
}
range_time(fac_loop, 1, 5)

data4 function() below combines the results of range_time for the 4 techniques

data4 <- function(n_min, n_max){
  data_loop <- range_time(fac_loop, n_min, n_max)[,2]
  data_Mem <- range_time(fac_Mem, n_min, n_max)[,2]
  data_Reduce <- range_time(fac_Reduce, n_min, n_max)[,2]
  data_Recursion <- range_time(fac_Recursion, n_min, n_max)[,2]
  data <- cbind(data_loop, data_Mem, data_Reduce, data_Recursion)
  names(data) <- c("Median_Loop_Time", "Median_Mem_Time", "Median_Redu_Time", "Median_Recu_Time")
  data$n <- n_min:n_max
  return(data)
}
data4(1,5)

Plot to take a look of the difference between the 4 techniques

plotTimeComparison <- function(n_min, n_max){
  df <- data4(n_min, n_max)
  df <- melt(df, id.vars = "n")
  df$n <- as.numeric(df$n)
  p <- ggplot(data = df, aes(x=n, y=value, colour = variable)) + geom_line()
  show(p)
  #return(df)
  }
plotTimeComparison(1,10)

#plotTimeComparison(10, 20)
LS0tDQp0aXRsZTogIiBGYWN0b3JpYWwgRnVuY3Rpb24gd2l0aCBmb3VyIHRlY2huaXF1ZXMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCmF1dGhvcjogVGhpYmF1dCBTYWFoDQpkYXRlOiAwMy8wNy8yMDE5DQotLS0NCg0KYGBge3J9DQpsaWJyYXJ5KHB1cnJyKQ0KbGlicmFyeShtaWNyb2JlbmNobWFyaykNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocmVzaGFwZTIpDQpgYGANCg0KIyBvdmVydmlldw0KDQpBZnRlciB3cml0aW5nIHlvdXIgZm91ciB2ZXJzaW9ucyBvZiB0aGUgRmFjdG9yaWFsIGZ1bmN0aW9uLCB1c2UgdGhlIG1pY3JvYmVuY2htYXJrIHBhY2thZ2UgdG8gdGltZSB0aGUgb3BlcmF0aW9uIG9mIHRoZXNlIGZ1bmN0aW9ucyBhbmQgcHJvdmlkZSBhIHN1bW1hcnkgb2YgdGhlaXIgcGVyZm9ybWFuY2UuIEluIGFkZGl0aW9uIHRvIHRpbWluZyB5b3VyIGZ1bmN0aW9ucyBmb3Igc3BlY2lmaWMgaW5wdXRzLCBtYWtlIHN1cmUgdG8gc2hvdyBhIHJhbmdlIG9mIGlucHV0cyBpbiBvcmRlciB0byBkZW1vbnN0cmF0ZSB0aGUgdGltaW5nIG9mIGVhY2ggZnVuY3Rpb24gZm9yIGxhcmdlciBpbnB1dHMuDQoNCg0KDQojIDEuIEZhY3RvcmlhbF9sb29wOiBDb21wdXRlcyB0aGUgZmFjdG9yaWFsIG9mIGFuIGludGVnZXIgdXNpbmcgbG9vcGluZy4NCg0KYGBge3J9DQpmYWNfbG9vcCA8LSBmdW5jdGlvbihuKXsNCiAgc3RvcGlmbm90KG4+PTApDQogIGlmIChuID09IDApew0KICAgIHJldHVybigxKQ0KICB9DQogIGVsc2Ugew0KICAgIHJlcyA8LSAxDQogICAgZm9yIChpIGluIDE6bil7DQogICAgICByZXMgPC0gcmVzICogaQ0KICAgIH0NCiAgICByZXR1cm4ocmVzKQ0KICB9DQp9DQpgYGANCg0KYGBge3J9DQpmYWNfbG9vcCg0KQ0KYGBgDQoNCg0KDQojIDIuIEZhY3RvcmlhbF9yZWR1Y2U6IENvbXB1dGVzIHRoZSBmYWN0b3JpYWwgdXNpbmcgdGhlIHJlZHVjZSgpLiANCg0KYGBge3J9DQpmYWNfUmVkdWNlIDwtIGZ1bmN0aW9uKG4pew0KICBzdG9waWZub3Qobj49MCkNCiAgIyBiZWNhdXNlIGZhY3RvcmllbCgwKT0xLCBpdCdzIGltcG9ydGFudCB0byBtYWtlIGNvbmRpdGlvbg0KICBpZiAobj09MCl7DQogICAgcmV0dXJuKDEpDQogIH0NCiAgZWxzZSB7DQogICAgcmVkdWNlKDE6biwgZnVuY3Rpb24oeCx5KXsNCiAgICAgIHgqeQ0KICAgIH0pDQogIH0NCn0NCmBgYA0KDQoNCmBgYHtyfQ0KZmFjX1JlZHVjZSg0KQ0KYGBgDQoNCg0KIyAzLiBGYWN0b3JpYWxfZnVuYzogVXNlcyByZWN1cnNpb24gdG8gY29tcHV0ZSB0aGUgZmFjdG9yaWFsLiANCg0KYGBge3J9DQpmYWNfUmVjdXJzaW9uIDwtIGZ1bmN0aW9uKG4pew0KICBzdG9waWZub3Qobj49MCkNCiAgaWYgKG49PTApew0KICAgIHJldHVybigxKQ0KICB9DQogIGVsc2Ugew0KICAgIHJldHVybihuKmZhY19SZWN1cnNpb24obi0xKSkNCiAgfQ0KfQ0KYGBgDQoNCg0KYGBge3J9DQpmYWNfUmVjdXJzaW9uKDQpDQpgYGANCg0KDQojIDQuIEZhY3RvcmlhbF9tZW06IFVzZXMgbWVtb3JpemF0aW9uIHRvIGNvbXB1dGUgdGhlIGZhY3RvcmlhbC4gDQoNCg0KYGBge3J9DQpmYWNfdGFibGUgPC0gYygxKQ0KDQpmYWNfTWVtIDwtIGZ1bmN0aW9uKG4pew0KICAjIEJlY2F1c2UgZmFjdG9yaWFsIG9mIG5lZ2F0aWYgbnVtYmVyIGRvZXMgbm90IGV4aXN0IHdlIHN0b3AgaWYgbjwwDQogIHN0b3BpZm5vdChuPj0wKQ0KICBpZiAobj09MCl7DQogICAgcmV0dXJuKDEpDQogIH0NCiAgZWxzZSB7DQogICAgaWYgKCFpcy5uYShmYWNfdGFibGVbbl0pKXsNCiAgICAgIHJldHVybihmYWNfdGFibGVbbl0pDQogICAgfSBlbHNlIHsNCiAgICAgIGZhY190YWJsZVtuLTFdIDw8LSBmYWNfTWVtKG4tMSkNCiAgICAgIHJldHVybihuKmZhY190YWJsZVtuLTFdKQ0KICAgIH0NCiAgfQ0KICANCn0NCmBgYA0KDQoNCmBgYHtyfQ0KZmFjX01lbSg0KQ0KYGBgDQoNCg0KDQojIDUuIHVzZSB0aGUgbWljcm9iZW5jaG1hcmsgcGFja2FnZToNCg0KdG8gdGltZSB0aGUgb3BlcmF0aW9uIG9mIHRoZXNlIGZ1bmN0aW9ucyBhbmQgcHJvdmlkZSBhIHN1bW1hcnkgb2YgdGhlaXIgcGVyZm9ybWFuY2UuSW4gYWRkaXRpb24gdG8gdGltaW5nIHlvdXIgZnVuY3Rpb25zIGZvciBzcGVjaWZpYyBpbnB1dHMsIG1ha2Ugc3VyZSB0byBzaG93IGEgcmFuZ2Ugb2YgaW5wdXRzIGluIG9yZGVyIHRvIGRlbW9uc3RyYXRlIHRoZSB0aW1pbmcgb2YgZWFjaCBmdW5jdGlvbiBmb3IgbGFyZ2VyIGlucHV0cy4gIA0KDQp0aGUgZnVuY3Rpb24gYmVsb3cgImNvbXBhcmVfdGltZSIgaXMgaW50dWl0aXZlLiBHaXZlbiBuIGl0IHByaW50IGEgZGF0YWZyYW1lIHdoZXJlIHdlIGNhbiBzZWUgdGhlIHN1bW1hcnkgb2YgMTAwIHRpbWUgb2YgY29tcHV0aW5nIG9mIGZhY290cmlhbChuKSB1c2luZyB0aGUgNCBkaWZmZXJlbnRzIHRlY2huaXF1ZS4gQW5kIGJ5IGxvb2tpbmcgdGhlIHJlc3VsdA0Kd2UgY2FuIGdldCBpbnNpZ2h0IGFib3V0IHRoZSB0aW1lIGNvbnN1bWluZyBvZiBkaWZmZXJlbnRzIHRlY2huaXF1ZXMuDQogDQogDQpgYGB7cn0NCmNvbXBhcmVfdGltZSA8LSBmdW5jdGlvbihuKXsNCiAgYXMuZGF0YS5mcmFtZShzdW1tYXJ5KG1pY3JvYmVuY2htYXJrKGZhY19sb29wKG4pLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY19NZW0obiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNfUmVjdXJzaW9uKG4pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjX1JlZHVjZShuKSkpKQ0KfQ0KYGBgDQogDQoNCmBgYHtyfQ0KY29tcGFyZV90aW1lKDUpDQpgYGANCg0KDQogcmFuZ2VfdGltZSgpIGZ1bmN0aW9uIGJlbG93IHRha2VzIGEgZ2l2ZW4gZmFjdG9yaWFsIGZ1bmN0aW9uIGFuZCBhIHJhbmdlDQogb2YgaW50ZWdlciAobl9taW46bl9tYXgpLCB0aGVuIGNvbXB1dGVzIHRoZSBtZWRpYW4gdGltZXMgb2YgMTAwIGNvbXB1dGluZyANCiBvZiBlYWNoIGludGVnZXIgd2l0aCB0aGUgZ2l2ZW4gZmFjdG9yaWFsIGZ1bmN0aW9uLg0KIA0KYGBge3J9DQpyYW5nZV90aW1lIDwtIGZ1bmN0aW9uKGYsIG5fbWluID0gMSwgbl9tYXggPSAxMCl7DQogIGRmX2Z1bmMgPC0gbWFwKHNlcShuX21pbiwgbl9tYXgpLCBmdW5jdGlvbih4KXttaWNyb2JlbmNobWFyayhmKHgpKSR0aW1lfSkNCiAgbmFtZXMoZGZfZnVuYykgPC0gcGFzdGUwKCJYIiwiLiIsIG5fbWluOm5fbWF4KQ0KICBkZl9mdW5jIDwtIGFzLmRhdGEuZnJhbWUoZGZfZnVuYykNCiAgZGZfZnVuYyAlPD4lDQogICAgZ2F0aGVyKG51bSwgdGltZSkgJT4lDQogICAgZ3JvdXBfYnkobnVtKSAlPiUNCiAgICBzdW1tYXJpc2UobWVkX3RpbWUgPSBtZWRpYW4odGltZSkpDQogIHJldHVybihkZl9mdW5jKQ0KfQ0KYGBgDQogDQoNCg0KYGBge3J9DQpyYW5nZV90aW1lKGZhY19sb29wLCAxLCA1KQ0KYGBgDQoNCiMgZGF0YTQgZnVuY3Rpb24oKSBiZWxvdyBjb21iaW5lcyB0aGUgcmVzdWx0cyBvZiByYW5nZV90aW1lIGZvciB0aGUgNCB0ZWNobmlxdWVzDQoNCg0KYGBge3J9DQpkYXRhNCA8LSBmdW5jdGlvbihuX21pbiwgbl9tYXgpew0KICBkYXRhX2xvb3AgPC0gcmFuZ2VfdGltZShmYWNfbG9vcCwgbl9taW4sIG5fbWF4KVssMl0NCiAgZGF0YV9NZW0gPC0gcmFuZ2VfdGltZShmYWNfTWVtLCBuX21pbiwgbl9tYXgpWywyXQ0KICBkYXRhX1JlZHVjZSA8LSByYW5nZV90aW1lKGZhY19SZWR1Y2UsIG5fbWluLCBuX21heClbLDJdDQogIGRhdGFfUmVjdXJzaW9uIDwtIHJhbmdlX3RpbWUoZmFjX1JlY3Vyc2lvbiwgbl9taW4sIG5fbWF4KVssMl0NCiAgZGF0YSA8LSBjYmluZChkYXRhX2xvb3AsIGRhdGFfTWVtLCBkYXRhX1JlZHVjZSwgZGF0YV9SZWN1cnNpb24pDQogIG5hbWVzKGRhdGEpIDwtIGMoIk1lZGlhbl9Mb29wX1RpbWUiLCAiTWVkaWFuX01lbV9UaW1lIiwgIk1lZGlhbl9SZWR1X1RpbWUiLCAiTWVkaWFuX1JlY3VfVGltZSIpDQogIGRhdGEkbiA8LSBuX21pbjpuX21heA0KICByZXR1cm4oZGF0YSkNCn0NCmBgYA0KDQoNCmBgYHtyfQ0KZGF0YTQoMSw1KQ0KYGBgDQoNCg0KDQojIFBsb3QgdG8gdGFrZSBhIGxvb2sgb2YgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgNCB0ZWNobmlxdWVzDQoNCmBgYHtyfQ0KcGxvdFRpbWVDb21wYXJpc29uIDwtIGZ1bmN0aW9uKG5fbWluLCBuX21heCl7DQogIGRmIDwtIGRhdGE0KG5fbWluLCBuX21heCkNCiAgZGYgPC0gbWVsdChkZiwgaWQudmFycyA9ICJuIikNCiAgZGYkbiA8LSBhcy5udW1lcmljKGRmJG4pDQogIHAgPC0gZ2dwbG90KGRhdGEgPSBkZiwgYWVzKHg9biwgeT12YWx1ZSwgY29sb3VyID0gdmFyaWFibGUpKSArIGdlb21fbGluZSgpDQogIHNob3cocCkNCiAgI3JldHVybihkZikNCiAgfQ0KYGBgDQoNCg0KYGBge3J9DQpwbG90VGltZUNvbXBhcmlzb24oMSwxMCkNCmBgYA0KDQoNCg0KYGBge3J9DQojcGxvdFRpbWVDb21wYXJpc29uKDEwLCAyMCkNCg0KYGBgDQoNCg0K