diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..b25c15b81fa --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/Instructions.md b/Instructions.md new file mode 100644 index 00000000000..7a8c502a4be --- /dev/null +++ b/Instructions.md @@ -0,0 +1,105 @@ +### Introduction + +This second programming assignment will require you to write an R +function that is able to cache potentially time-consuming computations. +For example, taking the mean of a numeric vector is typically a fast +operation. However, for a very long vector, it may take too long to +compute the mean, especially if it has to be computed repeatedly (e.g. +in a loop). If the contents of a vector are not changing, it may make +sense to cache the value of the mean so that when we need it again, it +can be looked up in the cache rather than recomputed. In this +Programming Assignment you will take advantage of the scoping rules of +the R language and how they can be manipulated to preserve state inside +of an R object. + +### Example: Caching the Mean of a Vector + +In this example we introduce the `<<-` operator which can be used to +assign a value to an object in an environment that is different from the +current environment. Below are two functions that are used to create a +special object that stores a numeric vector and caches its mean. + +The first function, `makeVector` creates a special "vector", which is +really a list containing a function to + +1. set the value of the vector +2. get the value of the vector +3. set the value of the mean +4. get the value of the mean + + + + makeVector <- function(x = numeric()) { + m <- NULL + set <- function(y) { + x <<- y + m <<- NULL + } + get <- function() x + setmean <- function(mean) m <<- mean + getmean <- function() m + list(set = set, get = get, + setmean = setmean, + getmean = getmean) + } + +The following function calculates the mean of the special "vector" +created with the above function. However, it first checks to see if the +mean has already been calculated. If so, it `get`s the mean from the +cache and skips the computation. Otherwise, it calculates the mean of +the data and sets the value of the mean in the cache via the `setmean` +function. + + cachemean <- function(x, ...) { + m <- x$getmean() + if(!is.null(m)) { + message("getting cached data") + return(m) + } + data <- x$get() + m <- mean(data, ...) + x$setmean(m) + m + } + +### Assignment: Caching the Inverse of a Matrix + +Matrix inversion is usually a costly computation and there may be some +benefit to caching the inverse of a matrix rather than computing it +repeatedly (there are also alternatives to matrix inversion that we will +not discuss here). Your assignment is to write a pair of functions that +cache the inverse of a matrix. + +Write the following functions: + +1. `makeCacheMatrix`: This function creates a special "matrix" object + that can cache its inverse. +2. `cacheSolve`: This function computes the inverse of the special + "matrix" returned by `makeCacheMatrix` above. If the inverse has + already been calculated (and the matrix has not changed), then + `cacheSolve` should retrieve the inverse from the cache. + +Computing the inverse of a square matrix can be done with the `solve` +function in R. For example, if `X` is a square invertible matrix, then +`solve(X)` returns its inverse. + +For this assignment, assume that the matrix supplied is always +invertible. + +In order to complete this assignment, you must do the following: + +1. Fork the GitHub repository containing the stub R files at + [https://github.com/rdpeng/ProgrammingAssignment2](https://github.com/rdpeng/ProgrammingAssignment2) + to create a copy under your own account. +2. Clone your forked GitHub repository to your computer so that you can + edit the files locally on your own machine. +3. Edit the R file contained in the git repository and place your + solution in that file (please do not rename the file). +4. Commit your completed R file into YOUR git repository and push your + git branch to the GitHub repository under your account. +5. Submit to Coursera the URL to your GitHub repository that contains + the completed R code for the assignment. + +### Grading + +This assignment will be graded via peer assessment. diff --git a/README.md b/README.md index 7a8c502a4be..9896f904550 100644 --- a/README.md +++ b/README.md @@ -1,105 +1,15 @@ -### Introduction +### README -This second programming assignment will require you to write an R -function that is able to cache potentially time-consuming computations. -For example, taking the mean of a numeric vector is typically a fast -operation. However, for a very long vector, it may take too long to -compute the mean, especially if it has to be computed repeatedly (e.g. -in a loop). If the contents of a vector are not changing, it may make -sense to cache the value of the mean so that when we need it again, it -can be looked up in the cache rather than recomputed. In this -Programming Assignment you will take advantage of the scoping rules of -the R language and how they can be manipulated to preserve state inside -of an R object. +This is my solution to Assignment 2, +caching the results of inverting a matrix, +for [R Programming](https://www.coursera.org/course/rprog). -### Example: Caching the Mean of a Vector +For the original README, see [Instructions](Instructions.md) -In this example we introduce the `<<-` operator which can be used to -assign a value to an object in an environment that is different from the -current environment. Below are two functions that are used to create a -special object that stores a numeric vector and caches its mean. +### Manifest -The first function, `makeVector` creates a special "vector", which is -really a list containing a function to + * README.md : this file + * Instructions.md : the original README, i.e. instructions + * cachematrix.R : my solution to the assignment + * testacachedmatrix.R : a simple test script for cachematrix.R -1. set the value of the vector -2. get the value of the vector -3. set the value of the mean -4. get the value of the mean - - - - makeVector <- function(x = numeric()) { - m <- NULL - set <- function(y) { - x <<- y - m <<- NULL - } - get <- function() x - setmean <- function(mean) m <<- mean - getmean <- function() m - list(set = set, get = get, - setmean = setmean, - getmean = getmean) - } - -The following function calculates the mean of the special "vector" -created with the above function. However, it first checks to see if the -mean has already been calculated. If so, it `get`s the mean from the -cache and skips the computation. Otherwise, it calculates the mean of -the data and sets the value of the mean in the cache via the `setmean` -function. - - cachemean <- function(x, ...) { - m <- x$getmean() - if(!is.null(m)) { - message("getting cached data") - return(m) - } - data <- x$get() - m <- mean(data, ...) - x$setmean(m) - m - } - -### Assignment: Caching the Inverse of a Matrix - -Matrix inversion is usually a costly computation and there may be some -benefit to caching the inverse of a matrix rather than computing it -repeatedly (there are also alternatives to matrix inversion that we will -not discuss here). Your assignment is to write a pair of functions that -cache the inverse of a matrix. - -Write the following functions: - -1. `makeCacheMatrix`: This function creates a special "matrix" object - that can cache its inverse. -2. `cacheSolve`: This function computes the inverse of the special - "matrix" returned by `makeCacheMatrix` above. If the inverse has - already been calculated (and the matrix has not changed), then - `cacheSolve` should retrieve the inverse from the cache. - -Computing the inverse of a square matrix can be done with the `solve` -function in R. For example, if `X` is a square invertible matrix, then -`solve(X)` returns its inverse. - -For this assignment, assume that the matrix supplied is always -invertible. - -In order to complete this assignment, you must do the following: - -1. Fork the GitHub repository containing the stub R files at - [https://github.com/rdpeng/ProgrammingAssignment2](https://github.com/rdpeng/ProgrammingAssignment2) - to create a copy under your own account. -2. Clone your forked GitHub repository to your computer so that you can - edit the files locally on your own machine. -3. Edit the R file contained in the git repository and place your - solution in that file (please do not rename the file). -4. Commit your completed R file into YOUR git repository and push your - git branch to the GitHub repository under your account. -5. Submit to Coursera the URL to your GitHub repository that contains - the completed R code for the assignment. - -### Grading - -This assignment will be graded via peer assessment. diff --git a/cachematrix.R b/cachematrix.R index a50be65aa44..1c8b2126bf2 100644 --- a/cachematrix.R +++ b/cachematrix.R @@ -1,15 +1,112 @@ -## Put comments here that give an overall description of what your -## functions do +## R Programming Assignment 2 +## Cacheing the inverse of a matrix -## Write a short comment describing this function +## Create a functtion that wraps a in closure with +## a list of functions that mutate both the matrix +## and a cached inverse of the matrix makeCacheMatrix <- function(x = matrix()) { + # Wrap a matrix in order to cache the value of its inverse + # + # Args: + # x: the matrix to wrap, defaults to the empty matrix + # + # Returns: + # A list of accessor and mutator functions for the + # matrix and its inverse + # initialize the inverse as NULL, aka yet unknown + inv <- NULL + + set <- function(y) { + # (Re)set the matrix + # + # Args: + # y: the new matrix to hold + # Returns: + # NULL + + # Reset both the matrix x and its inverse inv + x <<- y + inv <<- NULL + } + + get <- function() { + # Get the current matrix + # + # Args: + # None + # + # Returns: + # the current matrix + x + } + + setinverse <- function(inverse) { + # Sets the inverse of the matrix + # + # Note this caches a value computed elsewhere + # + # Args: + # inverse: the inverse matrix of x + # + # Returns: + # the value of inverse argument + + # store away a copy of the inverse + inv <<- inverse + } + + getinverse <- function() { + # Get the cached inverse matrix + # + # Args: + # None + # + # Returns: + # The cached value of the inverse matrix + + # fetch the inverse + inv + } + + # return a list of the above functions + list(set = set, + get = get, + setinverse = setinverse, + getinverse = getinverse) } -## Write a short comment describing this function +# Solve for the inverse of a matrix, but +# using a makeCacheMatrix wrapper to cache the results cacheSolve <- function(x, ...) { - ## Return a matrix that is the inverse of 'x' + # Return a matrix that is the inverse of x + # + # Args: + # x: matrix to invert, wrapped in a makeCacheMatrix + # ...: Additional argument to pass to solve() + # + # Returns: + # invese matrix of x + + # Try just pulling out a cached result + inv <- x$getinverse() + # if we got it just return it + if (!is.null(inv)) { + message("getting cached data") + return(inv) + } + + # otherwise, really do the work + + # grab the actual matrix + m <- x$get() + # compute its inverse + inv <- solve(m, ...) + # cache the result + x$setinverse(inv) + # and return the value we computed + inv } diff --git a/testcachedmatrix.R b/testcachedmatrix.R new file mode 100644 index 00000000000..2ff2cde5f72 --- /dev/null +++ b/testcachedmatrix.R @@ -0,0 +1,37 @@ +# +# Exercise makeCachedMatrix and cacheSolve +# + +source("cachematrix.R") +m1 <- matrix(c(1,1,1,3,4,3,3,3,4), nrow=3, ncol=3) +m2 <- matrix(c(1,0,5,2,1,6,3,4,0), nrow=3, ncol=3) + +cm <- makeCacheMatrix(m1) +message("original m1 matrix") +m1 +message("wrapped matrix should be the same") +cm$get() + +message("inverse using solve") +solve(m1) +message("inverse using cacheMatrix should be the same") +cacheSolve(cm) +message("running cacheSolve again should yeid cached results") +cacheSolve(cm) + +message("reset matrix to m2") +cm$set(m2) + +message("original m2") +m2 +message("wrapped matrix should be the same") +cm$get() +message("and cached inverse should be null") +cm$getinverse() + +message("inverse using solve") +solve(m2) +message("inverse using cacheMatrix should be the same") +cacheSolve(cm) +message("running cacheSolve again should yeid cached results") +cacheSolve(cm)