loopy_factorial <- function(n){
stopifnot(n >= 0) # prevents entry of a negative number which will prevent an infinite loop
number <- 1
for(i in n:1){
number <- i*number
}
if(number == 0){
1
} else {
number
}
}
reducy_factorial <- function(n){
stopifnot(n >= 0)
if(n == 0){
1
} else {
reduce(n:1, function(x,y){
x*y # x*y in reduce will actually provide a factorial of length n
})
}
}
funky_factorial <- function(n){
stopifnot(n >= 0)
if(n == 0){
1
} else if (n == 1){
1
} else {
n*funky_factorial(n-1) # this is the recursion line, multiplying n by the last multiple
}
}
memoizer <- function(){
res <- 1
memoizy_factorial <- function(n){
stopifnot(n >= 0)
if (n == 0) return(1)
if (n == 1) return (1)
if (!is.na(res[n])) return(res[n])
res[n] <<- n * funky_factorial(n-1) #replace the function to be used here
res[n]
}
memoizy_factorial
}
memoizy_factorial <- memoizer()
The functions were benchmarked to check efficiency of calculating factorials.
bm <- microbenchmark(loopy_factorial(20), reducy_factorial(20), funky_factorial(20), memoizy_factorial(20))
write.table(print(bm), file = "factorial_output.txt", sep = ' ', row.names = FALSE, col.names = TRUE)
## Unit: microseconds
## expr min lq mean median uq max neval
## loopy_factorial(20) 7.5 9.30 113.628 11.10 12.9 9957.8 100
## reducy_factorial(20) 234.4 268.15 607.950 306.20 444.7 14046.9 100
## funky_factorial(20) 119.4 136.10 230.416 154.55 177.5 2917.1 100
## memoizy_factorial(20) 8.4 10.15 584.654 14.20 19.2 56831.9 100