├── .DS_Store ├── .Rbuildignore ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── R ├── as.data.frame.rdeque.R ├── as.data.frame.rpqueue.R ├── as.data.frame.rstack.R ├── as.list.rdeque.R ├── as.list.rpqueue.R ├── as.list.rstack.R ├── as.rdeque.R ├── as.rdeque.default.R ├── as.rpqueue.R ├── as.rpqueue.default.R ├── as.rstack.R ├── as.rstack.default.R ├── empty.R ├── empty.rdeque.R ├── empty.rpqueue.R ├── empty.rstack.R ├── fixd.R ├── fixd.rdeque.R ├── head.rdeque.R ├── head.rpqueue.R ├── head.rstack.R ├── insert_back.R ├── insert_back.rdeque.R ├── insert_back.rpqueue.R ├── insert_front.R ├── insert_front.rdeque.R ├── insert_top.R ├── insert_top.rstack.R ├── length.rdeque.R ├── length.rpqueue.R ├── length.rstack.R ├── makeequal.R ├── makeequal.rpqueue.R ├── peek_back-set.R ├── peek_back-set.rdeque.R ├── peek_back.R ├── peek_back.rdeque.R ├── peek_front-set.R ├── peek_front-set.rdeque.R ├── peek_front-set.rpqueue.R ├── peek_front.R ├── peek_front.rdeque.R ├── peek_front.rpqueue.R ├── peek_top-set.R ├── peek_top-set.rstack.R ├── peek_top.R ├── peek_top.rstack.R ├── print.rdeque.R ├── print.rpqueue.R ├── print.rstack.R ├── rdeque.R ├── rev.rstack.R ├── rotate.R ├── rotate.rpqueue.R ├── rpqueue.R ├── rstack.R ├── rstacknode.R ├── without_back.R ├── without_back.rdeque.R ├── without_front.R ├── without_front.rdeque.R ├── without_front.rpqueue.R ├── without_top.R └── without_top.rstack.R ├── README.Rmd ├── README.html ├── README.md ├── man ├── as.data.frame.rdeque.Rd ├── as.data.frame.rstack.Rd ├── as.list.rdeque.Rd ├── as.list.rstack.Rd ├── as.rdeque.Rd ├── as.rstack.Rd ├── head.rstack.Rd ├── insert_back.Rd ├── insert_front.Rd ├── insert_top.Rd ├── length.rdeque.Rd ├── length.rstack.Rd ├── peek_back.Rd ├── peek_front.Rd ├── peek_top.Rd ├── rdeque.Rd ├── rev.rstack.Rd ├── rstack.Rd ├── rstacknode.Rd ├── without_back.Rd ├── without_front.Rd └── without_top.Rd ├── rstackdeque.Rproj └── tests ├── testthat.R └── testthat ├── test.rdeque.R ├── test.rpqueue.R └── test.stack.R /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneilsh/rstackdeque/c3215330a0c1d24db4c5b17ea598b5da0b46a291/.DS_Store -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | rstackdeque_rstudio.Rproj 2 | .Rproj.user 3 | .Rhistory 4 | .RData 5 | man/* 6 | 1-review-1_response.txt 7 | rstackdeque_oneil_rjournal_4_13_2015.zip 8 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: rstackdeque 2 | Type: Package 3 | Title: Persistent Fast Amortized Stack and Queue Data Structures 4 | Version: 1.1.1 5 | Date: 2014-12-01 6 | URL: https://github.com/oneilsh/rstackdeque 7 | BugReports: https://github.com/oneilsh/rstackdeque/issues 8 | Author: Shawn T. O'Neil 9 | Maintainer: Shawn T. O'Neil 10 | Description: Provides fast, persistent (side-effect-free) stack, queue and 11 | deque (double-ended-queue) data structures. While deques include a superset 12 | of functionality provided by queues, in these implementations queues are 13 | more efficient in some specialized situations. See the documentation for 14 | rstack, rdeque, and rpqueue for details. 15 | License: MIT + file LICENSE 16 | Suggests: 17 | testthat 18 | Depends: 19 | utils 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2015 2 | COPYRIGHT HOLDER: Shawn T. O'Neil 3 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2 (4.1.1): do not edit by hand 2 | 3 | S3method("peek_back<-",rdeque) 4 | S3method("peek_front<-",rdeque) 5 | S3method("peek_front<-",rpqueue) 6 | S3method("peek_top<-",rstack) 7 | S3method(as.data.frame,rdeque) 8 | S3method(as.data.frame,rpqueue) 9 | S3method(as.data.frame,rstack) 10 | S3method(as.list,rdeque) 11 | S3method(as.list,rpqueue) 12 | S3method(as.list,rstack) 13 | S3method(as.rdeque,default) 14 | S3method(as.rpqueue,default) 15 | S3method(as.rstack,default) 16 | S3method(empty,rdeque) 17 | S3method(empty,rpqueue) 18 | S3method(empty,rstack) 19 | S3method(fixd,rdeque) 20 | S3method(head,rdeque) 21 | S3method(head,rpqueue) 22 | S3method(head,rstack) 23 | S3method(insert_back,rdeque) 24 | S3method(insert_back,rpqueue) 25 | S3method(insert_front,rdeque) 26 | S3method(insert_top,rstack) 27 | S3method(length,rdeque) 28 | S3method(length,rpqueue) 29 | S3method(length,rstack) 30 | S3method(makeequal,rpqueue) 31 | S3method(peek_back,rdeque) 32 | S3method(peek_front,rdeque) 33 | S3method(peek_front,rpqueue) 34 | S3method(peek_top,rstack) 35 | S3method(print,rdeque) 36 | S3method(print,rpqueue) 37 | S3method(print,rstack) 38 | S3method(rev,rstack) 39 | S3method(rotate,rpqueue) 40 | S3method(without_back,rdeque) 41 | S3method(without_front,rdeque) 42 | S3method(without_front,rpqueue) 43 | S3method(without_top,rstack) 44 | export("peek_back<-") 45 | export("peek_front<-") 46 | export("peek_top<-") 47 | export(as.rdeque) 48 | export(as.rpqueue) 49 | export(as.rstack) 50 | export(empty) 51 | export(fixd) 52 | export(insert_back) 53 | export(insert_front) 54 | export(insert_top) 55 | export(makeequal) 56 | export(peek_back) 57 | export(peek_front) 58 | export(peek_top) 59 | export(rdeque) 60 | export(rotate) 61 | export(rpqueue) 62 | export(rstack) 63 | export(rstacknode) 64 | export(without_back) 65 | export(without_front) 66 | export(without_top) 67 | import(utils) 68 | -------------------------------------------------------------------------------- /R/as.data.frame.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Convert an rdeque to a data.frame 3 | #' 4 | #' @description Converts the elements of an rdeque into rows of a data.frame, if this is reasonable. 5 | #' 6 | #' @details This function runs in \eqn{O(N)} time in the size of the rdeque, and will only work if all 7 | #' elements of the deque have the same \code{length()} (e.g., same number of columns), and if any of the 8 | #' elements have names, then those names do not conflict (e.g., same column names where used). 9 | #' This is accomplished by a call to 10 | #' \code{do.call("rbind", as.list.rdeque(x))}, where \code{\link{as.list.rdeque}} converts the rdeque to a list 11 | #' where the front element becomes the first element of the list. 12 | #' @param x rdeque to convert. 13 | #' @param row.names passed on to \code{as.data.frame} before final conversion. 14 | #' @param optional passed onto \code{as.data.frame} before final conversion. 15 | #' @param ... passed onto \code{as.data.frame} before final conversion. 16 | #' @return a data.frame with the first row the previous front of the deque and last row the previous back. 17 | #' @seealso \code{\link{as.list.rdeque}} for conversion to a list and the generic \code{\link{as.data.frame}}. 18 | #' @examples 19 | #' d <- rdeque() 20 | #' d <- insert_front(d, data.frame(names = c("Bob", "Joe"), ages = c(25, 18))) 21 | #' d <- insert_front(d, data.frame(names = c("Mary", "Kate", "Ashley"), ages = c(27, 26, 21))) 22 | #' print(d) 23 | #' 24 | #' dd <- as.data.frame(d) 25 | #' print(dd) 26 | #' 27 | #' ## Elements may be similarly-named lists as well, representing individual rows: 28 | #' d <- rdeque() 29 | #' d <- insert_front(d, list(name = "Bob", age = 25)) 30 | #' d <- insert_front(d, list(name = "Mary", age = 24)) 31 | #' print(d) 32 | #' 33 | #' dd <- as.data.frame(d) 34 | #' print(dd) 35 | #' 36 | #' ## Building a deque in a loop, converting to a dataframe after the fact: 37 | #' d <- rdeque() 38 | #' for(i in 1:1000) { 39 | #' if(runif(1,0,1) < 0.5) { 40 | #' d <- insert_front(d, data.frame(i = i, type = "sqrt", val = sqrt(i))) 41 | #' } else { 42 | #' d <- insert_back(d, data.frame(i = i, type = "log", val = log(i))) 43 | #' } 44 | #' if(i %% 100 == 0) { 45 | #' print(i/1000) 46 | #' } 47 | #' } 48 | #' print(head(as.data.frame(d))) 49 | as.data.frame.rdeque <- function(x, row.names = NULL, optional = FALSE, ...) { 50 | dlist <- lapply(as.list(x), as.data.frame, optional = optional, ...) 51 | uniquelens <- unique(lapply(dlist, length)) 52 | if(length(uniquelens) > 1) { 53 | stop("cannot convert an rdeque to a data.frame unless all elements have the same length()") 54 | } 55 | uniquenamesets <- unique(lapply(dlist, names)) 56 | if(length(uniquenamesets) > 1) { 57 | stop("cannot convert an rdeque to a data.frame when elements have contradictory names()") 58 | } 59 | return(as.data.frame(do.call(rbind, dlist), row.names, optional, ...)) 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /R/as.data.frame.rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Convert an rpqueue to a data.frame 3 | #' 4 | #' @description Converts the elements of an rpqueue into rows of a data.frame, if this is reasonable. 5 | #' 6 | #' @details This function runs in \eqn{O(N)} time in the size of the rpqueue, and will only work if all 7 | #' elements of the queue have the same \code{length()} (e.g., same number of columns), and if any of the 8 | #' elements have names, then those names do not conflict (e.g., same column names where used). 9 | #' This is accomplished by a call to 10 | #' \code{do.call("rbind", as.list.rpqueue(x))}, where \code{\link{as.list.rpqueue}} converts the rpqueue to a list 11 | #' where the front element becomes the first element of the list. 12 | #' @param x rpqueue to convert. 13 | #' @param row.names passed on to \code{as.data.frame} before final conversion. 14 | #' @param optional passed onto \code{as.data.frame} before final conversion. 15 | #' @param ... passed onto \code{as.data.frame} before final conversion. 16 | #' @return a data.frame with the first row the previous front of the queue and last row the previous back. 17 | #' @seealso \code{\link{as.list.rpqueue}} for conversion to a list and the generic \code{\link{as.data.frame}}. 18 | #' @examples 19 | #' q <- rpqueue() 20 | #' q <- insert_back(q, data.frame(names = c("Bob", "Joe"), ages = c(25, 18))) 21 | #' q <- insert_back(q, data.frame(names = c("Mary", "Kate", "Ashley"), ages = c(27, 26, 21))) 22 | #' print(q) 23 | #' 24 | #' qq <- as.data.frame(q) 25 | #' print(qq) 26 | #' 27 | #' ## Elements may be similarly-named lists as well, representing individual rows: 28 | #' q <- rpqueue() 29 | #' q <- insert_back(q, list(name = "Bob", age = 25)) 30 | #' q <- insert_back(q, list(name = "Mary", age = 24)) 31 | #' print(q) 32 | #' 33 | #' qq <- as.data.frame(q) 34 | #' print(qq) 35 | #' 36 | #' ## Building a deque in a loop, converting to a dataframe after the fact: 37 | #' q <- rpqueue() 38 | #' for(i in 1:1000) { 39 | #' if(runif(1,0,1) < 0.5) { 40 | #' q <- insert_back(q, data.frame(i = i, type = "sqrt", val = sqrt(i))) 41 | #' } else { 42 | #' q <- insert_back(q, data.frame(i = i, type = "log", val = log(i))) 43 | #' } 44 | #' if(i %% 100 == 0) { 45 | #' print(i/1000) 46 | #' } 47 | #' } 48 | #' print(head(as.data.frame(q))) 49 | as.data.frame.rpqueue <- function(x, row.names = NULL, optional = FALSE, ...) { 50 | dlist <- lapply(as.list(x), as.data.frame, optional = optional, ...) 51 | uniquelens <- unique(lapply(dlist, length)) 52 | if(length(uniquelens) > 1) { 53 | stop("cannot convert an rpqueue to a data.frame unless all elements have the same length()") 54 | } 55 | uniquenamesets <- unique(lapply(dlist, names)) 56 | if(length(uniquenamesets) > 1) { 57 | stop("cannot convert an rpqueue to a data.frame when elements have contradictory names()") 58 | } 59 | return(as.data.frame(do.call(rbind, dlist), row.names, optional, ...)) 60 | } -------------------------------------------------------------------------------- /R/as.data.frame.rstack.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Convert an rstack to a data.frame 3 | #' 4 | #' @description Converts the elements of an rstack into rows of a data.frame, if this is reasonable. 5 | #' 6 | #' @details This function runs in \eqn{O(N)} time in the size of the rstack, and will only work if all 7 | #' elements of the stack have the same length() (e.g., same number of columns), and if any of the 8 | #' elements have names, then those names do not conflict (e.g., same column names where used). 9 | #' This is accomplished by a call to 10 | #' \code{do.call("rbind", as.list.rstack(x))}, where \code{\link{as.list.rstack}} converts the rstack to a list 11 | #' where the top element becomes the first element of the list. 12 | #' @param x rstack to convert. 13 | #' @param row.names passed on to \code{as.data.frame} before final conversion. 14 | #' @param optional passed onto \code{as.data.frame} before final conversion. 15 | #' @param ... passed onto \code{as.data.frame} before final conversion. 16 | #' @return a data.frame with the first row the previous top of the stack. 17 | #' @seealso \code{\link{as.list.rstack}} for conversion to a list and the generic \code{\link{as.data.frame}}. 18 | #' @examples 19 | #' s <- rstack() 20 | #' s <- insert_top(s, data.frame(names = c("Bob", "Joe"), ages = c(25, 18))) 21 | #' s <- insert_top(s, data.frame(names = c("Mary", "Kate", "Ashley"), ages = c(27, 26, 21))) 22 | #' print(s) 23 | #' 24 | #' sd <- as.data.frame(s) 25 | #' print(sd) 26 | #' 27 | #' ## Elements may be similarly-named lists as well, representing individual rows: 28 | #' s <- rstack() 29 | #' s <- insert_top(s, list(name = "Bob", age = 25)) 30 | #' s <- insert_top(s, list(name = "Mary", age = 24)) 31 | #' print(s) 32 | #' 33 | #' sd <- as.data.frame(s) 34 | #' print(sd) 35 | #' 36 | #' ## Building a stack in a loop, converting to a dataframe after the fact: 37 | #' s <- rstack() 38 | #' for(i in 1:1000) { 39 | #' if(runif(1,0,1) < 0.5) { 40 | #' s <- insert_top(s, data.frame(i = i, type = "sqrt", val = sqrt(i))) 41 | #' } else { 42 | #' s <- insert_top(s, data.frame(i = i, type = "log", val = log(i))) 43 | #' } 44 | #' if(i %% 100 == 0) { 45 | #' print(i/1000) 46 | #' } 47 | #' } 48 | #' print(head(as.data.frame(s))) 49 | as.data.frame.rstack <- function(x, row.names = NULL, optional = FALSE, ...) { 50 | dlist <- lapply(as.list(x), as.data.frame, optional = optional, ...) 51 | uniquelens <- unique(lapply(dlist, length)) 52 | if(length(uniquelens) > 1) { 53 | stop("cannot convert an rstack to a data.frame unless all elements have the same length()") 54 | } 55 | uniquenamesets <- unique(lapply(dlist, names)) 56 | if(length(uniquenamesets) > 1) { 57 | stop("cannot convert an rstack to a data.frame when elements have contradictory names()") 58 | } 59 | return(as.data.frame(do.call(rbind, dlist), row.names, optional, ...)) 60 | } -------------------------------------------------------------------------------- /R/as.list.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Convert an rdeque to a list 3 | #' 4 | #' @description Converts an rdeque to a list, where the front of the deque becomes 5 | #' the first element of the list, the second-from-front the second, and so on. 6 | #' 7 | #' @details Runs in \eqn{O(N)} time in the size of the rdeque, but the generated list is pre-allocated for efficiency. 8 | #' @param x rdeque to convert. 9 | #' @param ... additional arguments passed to as.list after initial conversion to list. 10 | #' @return a list containing the elements of the rdeqeue in front-to-back order. 11 | #' @seealso \code{\link{as.data.frame.rstack}} and the generic \code{\link{as.list}}. 12 | #' @examples 13 | #' d <- rdeque() 14 | #' d <- insert_front(d, "a") 15 | #' d <- insert_front(d, "b") 16 | #' 17 | #' dlist <- as.list(d) 18 | #' print(dlist) 19 | as.list.rdeque <- function(x, ...) { 20 | return(as.list(c(as.list(x$l), rev(as.list(x$r))), ...)) 21 | } -------------------------------------------------------------------------------- /R/as.list.rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Convert an rpqueue to a list 3 | #' 4 | #' @description Converts an rpqueue to a list, where the front of the queue becomes 5 | #' the first element of the list, the second-from-front the second, and so on. 6 | #' 7 | #' @details Runs in \eqn{O(N)} time in the size of the rpqueue, but the generated list is pre-allocated for efficiency. 8 | #' @param x rpqueue to convert. 9 | #' @param ... additional arguments passed to as.list after initial conversion to list. 10 | #' @return a list containing the elements of the rpqueue in front-to-back order. 11 | #' @seealso \code{\link{as.data.frame.rpqueue}} and the generic \code{\link{as.list}}. 12 | #' @examples 13 | #' q <- rpqueue() 14 | #' q <- insert_back(q, "a") 15 | #' q <- insert_back(q, "b") 16 | #' 17 | #' qlist <- as.list(q) 18 | #' print(qlist) 19 | #' @export 20 | as.list.rpqueue <- function(x, ...) { 21 | return(as.list(c(as.list(x$l), rev(as.list(x$r))), ...)) 22 | } 23 | 24 | -------------------------------------------------------------------------------- /R/as.list.rstack.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Convert an rstack to a list 3 | #' 4 | #' @description Converts an rstack to a list, where the top of the stack becomes 5 | #' the first element of the list, the second-from-top the second, and so on. 6 | #' 7 | #' @details Runs in \eqn{O(N)} time in the size of the stack, but the generated list is pre-allocated for efficiency. 8 | #' @param x rstack to convert. 9 | #' @param ... additional arguments passed to as.list after initial conversion to list. 10 | #' @return a list containing the elements of the stack in top-to-bottom order. 11 | #' @seealso \code{\link{as.data.frame.rstack}} 12 | #' @examples 13 | #' s <- rstack() 14 | #' s <- insert_top(s, "a") 15 | #' s <- insert_top(s, "b") 16 | #' 17 | #' slist <- as.list(s) 18 | #' print(slist) 19 | as.list.rstack <- function(x, ...) { 20 | retlist <- vector("list", x$len) 21 | node <- x$head 22 | index <- 1 23 | while(!is.null(node)) { 24 | retlist[[index]] <- node$data 25 | node <- node$nextnode 26 | index <- index + 1 27 | } 28 | return(as.list(retlist, ...)) 29 | } -------------------------------------------------------------------------------- /R/as.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Create a pre-filled rdeque from a given input 3 | #' 4 | #' @description Creates a new rdeque from a given input. Coerces input to a 5 | #' list first using \code{as.list}, the element at \code{x[[1]]} becomes the front of the new rdeque. 6 | #' 7 | #' @details Runs in \eqn{O(N)} in the size of the input. Because data.frames return a list of 8 | #' columns when run through \code{as.list}, running \code{as.rdeque} results in a deque of 9 | #' columns, rather than a deque of rows. 10 | #' @param x input to convert to an rdeque. 11 | #' @param ... additional arguments to be passed to or from methods (ignored). 12 | #' @return a new rdeque. 13 | #' @seealso \code{\link{rdeque}}. 14 | #' @examples 15 | #' d <- as.rdeque(1:20) 16 | #' print(d) 17 | #' 18 | #' d <- as.rdeque(1:200000) 19 | #' print(d) 20 | #' 21 | #' ## A deck with only 5 elements, one for each column 22 | #' oops <- as.rdeque(iris) 23 | #' print(oops) 24 | as.rdeque <- function(x, ...) {UseMethod("as.rdeque", x)} -------------------------------------------------------------------------------- /R/as.rdeque.default.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Default method for converting to an rdeque 3 | #' @description Default method for converting to an rdeque. 4 | #' @details Elements from the input (of any type) are first converted to a list with \code{\link{as.list}}, 5 | #' after this an rdeque of the appropriate size is created holding the elements. The element at \code{x[[1]]} 6 | #' becomes the front of the rdeque. Runs in time \eqn{O(n)}, in the size of the number of elements contained in the resulting rdeque. 7 | #' @param x the input to convert to an rdeque 8 | #' @param ... arguments to be passed to or from other methods (ignored). 9 | #' @return a filled \code{\link{rdeque}}. 10 | #' @seealso \code{\link{rdeque}} for info about rdeques, \code{\link{as.rdeque}} for the generic function. 11 | as.rdeque.default <- function(x, ...) { 12 | input <- x 13 | newd <- rdeque() 14 | if(length(input) == 0) { 15 | return(newd) 16 | } else if(length(input) == 1) { 17 | newd$r <- insert_top(newd$r, as.list(input)[[1]]) 18 | return(newd) 19 | } else { 20 | alllist <- as.list(input) 21 | mid <- as.integer(length(alllist)/2) 22 | left <- alllist[1:mid] 23 | right <- rev(alllist[(mid+1):length(alllist)]) 24 | 25 | newd <- rdeque() 26 | newd$l <- as.rstack(left) 27 | newd$r <- as.rstack(right) 28 | return(newd) 29 | } 30 | } -------------------------------------------------------------------------------- /R/as.rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Create a pre-filled rpqueue from a given input 3 | #' 4 | #' @description Creates a new rpqueue from a given input. Coerces input to a 5 | #' list first using \code{as.list}, the element at \code{x[[1]]} becomes the front of the new queue. 6 | #' 7 | #' @details Runs in \eqn{O(N)} in the size of the input. Because data.frames return a list of 8 | #' columns when run through \code{as.list}, running \code{as.rpqueue} results in a queue of 9 | #' columns, rather than a queue of rows. 10 | #' @param x input to convert to an rpqueue. 11 | #' @param ... additional arguments to be passed to or from methods (ignored). 12 | #' @return a new rpqueue. 13 | #' @seealso \code{\link{rpqueue}}. 14 | #' @examples 15 | #' d <- as.rpqueue(1:20) 16 | #' print(d) 17 | #' 18 | #' ## A queue with only 5 elements, one for each column 19 | #' oops <- as.rdeque(iris) 20 | #' print(oops) 21 | as.rpqueue <- function(x, ...) {UseMethod("as.rpqueue", x)} -------------------------------------------------------------------------------- /R/as.rpqueue.default.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Default method for converting to an rpqueue 3 | #' @description Default method for converting to an rpqueue. 4 | #' @details Elements from the input (of any type) are first converted to a list with \code{\link{as.list}}, 5 | #' after this an rpqueue of the appropriate size is created holding the elements. The element at \code{x[[1]]} 6 | #' becomes the front of the rpqueue. Runs in time \eqn{O(n)}. 7 | #' @param x the input to convert to an rpqueue. 8 | #' @param ... arguments to be passed to or from other methods (ignored). 9 | #' @return a filled \code{\link{rpqueue}}. 10 | #' @seealso \code{\link{rpqueue}} for info about rpqueues, \code{\link{as.rpqueue}} for the generic function. 11 | as.rpqueue.default <- function(x, ...) { 12 | retq <- rpqueue() 13 | for(el in as.list(x)) { 14 | retq <- insert_back(retq, el) 15 | } 16 | return(retq) 17 | } 18 | 19 | -------------------------------------------------------------------------------- /R/as.rstack.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Create an rstack pre-filled from a given input 3 | #' 4 | #' @description Creates a new rstack from a given input. Coerces input to a 5 | #' list first using \code{as.list}, the element at \code{x[[1]]} becomes the top of the new rstack. 6 | #' 7 | #' @details Runs in \eqn{O(N)} in the size of the input. Because data frames return a list of 8 | #' columns when run through \code{as.list}, running \code{as.rstack} results in a stack of 9 | #' columns, rather than a stack of rows. 10 | #' @param x input to convert to a stack. 11 | #' @param ... additional arguments to be passed to or from methods. 12 | #' @return a new rstack. 13 | #' @seealso \code{\link{rstack}}. 14 | #' @examples 15 | #' s <- as.rstack(1:20) 16 | #' print(s) 17 | #' 18 | #' s <- as.rstack(1:200000) 19 | #' print(s) 20 | #' 21 | #' ## A stack with only 5 elements, one for each column 22 | #' oops <- as.rstack(iris) 23 | #' print(oops) 24 | as.rstack <- function(x, ...) {UseMethod("as.rstack", x)} -------------------------------------------------------------------------------- /R/as.rstack.default.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Default method for converting to an rstack 3 | #' @description Default method for converting to an rstack. 4 | #' @details Elements from the input (of any type) are first converted to a list with \code{\link{as.list}}, 5 | #' after this an rstack of the appropriate size is created holding the elements. The element at \code{x[[1]]} 6 | #' becomes the top of the stack. 7 | #' @param x the input to convert to an rstack. 8 | #' @param ... arguments to be passed to or from other methods (ignored). 9 | #' @return a filled \code{\link{rstack}}. 10 | #' @seealso \code{\link{rstack}} for info about rstacks, \code{\link{as.rstack}} for the generic. 11 | as.rstack.default <- function(x, ...) { 12 | input <- x 13 | lastnode <- NULL 14 | listin <- rev(as.list(input)) 15 | for(el in listin) { 16 | newnode <- rstacknode(el) 17 | newnode$nextnode <- lastnode 18 | lastnode <- newnode 19 | } 20 | newstack <- rstack() 21 | newstack$head <- lastnode 22 | newstack$len <- length(listin) 23 | return(newstack) 24 | } -------------------------------------------------------------------------------- /R/empty.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Check if an rstack, rdeque, or rpqueue is empty 3 | #' 4 | #' @description Check if an rstack, rdeque, or rpqueue is empty. 5 | #' @details Runs in \eqn{O(1)} time for all types. 6 | #' 7 | #' @param x rstack, rdeque, or rpqueue to check. 8 | #' @param ... additional arguments to be passed to or from methods (ignored). 9 | #' @return logical vector of length 1. 10 | #' @examples 11 | #' s <- rstack() 12 | #' print(empty(s)) ## TRUE 13 | #' s <- insert_top(s, "a") 14 | #' print(empty(s)) ## FALSE 15 | empty <- function(x, ...) {UseMethod("empty", x)} -------------------------------------------------------------------------------- /R/empty.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Check if an rdeque is empty 3 | #' @description Check if an rdeque is empty. 4 | #' @details Runs in \eqn{O(1)} time. 5 | #' @param x the rdeque to check. 6 | #' @param ... additional arguments to be passed to or from methods (ignored). 7 | #' @return logical vector of length 1. 8 | #' @seealso \code{\link{empty}} for the generic function that can be used on rstacks, rdeques, and rpqueues. 9 | empty.rdeque <- function(x, ...) { 10 | if(length(x) < 1) { 11 | return(TRUE) 12 | } else { 13 | return(FALSE) 14 | } 15 | } 16 | 17 | 18 | -------------------------------------------------------------------------------- /R/empty.rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Check if an rpqueue is empty 3 | #' @description Check if an rpqueue is empty. 4 | #' @details Runs in \eqn{O(1)} time. 5 | #' @param x the rpqueue to check. 6 | #' @param ... additional arguments to be passed to or from methods (ignored). 7 | #' @return logical vector of length 1. 8 | #' @seealso \code{\link{empty}} for the generic function that can be used on rstacks, rdeques, and rpqueues. 9 | empty.rpqueue <- function(x, ...) { 10 | if(length(x) > 0) {return(FALSE)} 11 | return(TRUE) 12 | } 13 | 14 | -------------------------------------------------------------------------------- /R/empty.rstack.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Check if an rstack is empty 3 | #' @description Check if an rstack is empty. 4 | #' @details Runs in \eqn{O(1)} time. 5 | #' @param x the rstack to check. 6 | #' @param ... additional arguments to be passed to or from methods (ignored). 7 | #' @return logical vector of length 1. 8 | #' @seealso \code{\link{empty}} for the generic function that can be used on rstacks, rdeques, and rpqueues. 9 | empty.rstack <- function(x, ...) { 10 | if(length(x) < 1) { 11 | return(TRUE) 12 | } else { 13 | return(FALSE) 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /R/fixd.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Fix an rdeque 3 | #' 4 | #' @description Maintains the invariant that there is always something in two stacks used by 5 | #' rdeques under the hood so long as there is 2 more elements in the rdeque. 6 | #' 7 | #' @details In fact, fix will be called whenever there are fewer than 6 elements in both 8 | #' the front and end of the deque. Generally this method is \eqn{O(N)}, and so a full copy is returned. 9 | #' @param d rdeque to fix. 10 | #' @param ... additional arguments to be passed to or from methods (ignored). 11 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 12 | #' @return fixed, "balanced" deque. 13 | fixd <- function(d, ...) {UseMethod("fixd", d)} -------------------------------------------------------------------------------- /R/fixd.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Fix an rdeque 3 | #' @description A method used behind the scenes to provide \eqn{O(1)}-amortized time for most operations. 4 | #' Runs in \eqn{O(n)} time worst case; restructures the rdeque so that the two internal rstacks 5 | #' are roughly the same length. 6 | #' @param d The rdeque to fix. 7 | #' @param ... additional arguments to be passed to or from methods. 8 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 9 | #' @return a fixed deque. 10 | fixd.rdeque <- function(d, ...) { 11 | if(length(d) < 2 | (length(d$l) > 6 & length(d$r) > 6)) { 12 | return(d) 13 | } else { 14 | alllist <- c(as.list(d$l), rev(as.list(d$r))) 15 | mid <- as.integer(length(alllist)/2) 16 | left <- alllist[1:mid] 17 | right <- rev(alllist[(mid+1):length(alllist)]) 18 | 19 | newd <- rdeque() 20 | newd$l <- as.rstack(left) 21 | newd$r <- as.rstack(right) 22 | return(newd) 23 | } 24 | } -------------------------------------------------------------------------------- /R/head.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @import utils 3 | #' @title Return the first n elements of an rdeque as an rdeque 4 | #' 5 | #' @description Returns the first n elements of a deque as a deque, or all of the elements if its length is less than n. 6 | #' 7 | #' @details Runs in \eqn{O(n)} time (in the size of the number of elements requested). 8 | #' @param x rdeque to get the head of. 9 | #' @param ... arguments to be passed to or from other methods (ignored). 10 | #' @param n number of elements to get. 11 | #' @return a new rdeque. 12 | #' @examples 13 | #' d <- rdeque() 14 | #' d <- insert_back(d, "a") 15 | #' d <- insert_back(d, "b") 16 | #' d <- insert_back(d, "c") 17 | #' 18 | #' dt <- head(d, n = 2) 19 | #' print(dt) 20 | head.rdeque <- function(x, n = 6L, ...) { 21 | newdeque <- rdeque() 22 | if(n < 0) { 23 | n = max(n, -1*length(x)) 24 | n = length(x) + n 25 | } 26 | if(n > length(x)) { 27 | n = length(x) 28 | } 29 | if(n == 0) { 30 | return(newdeque) 31 | } 32 | for(i in seq(1,n)) { 33 | newdeque <- insert_back(newdeque, peek_front(x)) 34 | x <- without_front(x) 35 | } 36 | return(newdeque) 37 | } -------------------------------------------------------------------------------- /R/head.rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @import utils 3 | #' @title Return the head (front) of an rpqueue 4 | #' 5 | #' @description Returns the first \eqn{n} elements of an rpqueue as an rpqueue, or all of the elements 6 | #' if \code{length(x) < n}. 7 | #' 8 | #' @details Runs in \eqn{O(n)} time (in the size of the number of elements requested). 9 | #' @param x rpqueue to get the head/top of. 10 | #' @param n number of elements to get. 11 | #' @param ... arguments to be passed to or from other methods (ignored). 12 | #' @return an \code{\link{rpqueue}}. 13 | #' @seealso \code{\link{rpqueue}}. 14 | #' @examples 15 | #' q <- rpqueue() 16 | #' q <- insert_back(q, "a") 17 | #' q <- insert_back(q, "b") 18 | #' q <- insert_back(q, "c") 19 | #' 20 | #' qt <- head(q, n = 2) 21 | #' print(qt) 22 | head.rpqueue <- function(x, n = 6L, ...) { 23 | newrpqueue <- rpqueue() 24 | if(n < 0) { 25 | n = max(n, -1*length(x)) 26 | n = length(x) + n 27 | } 28 | if(n > length(x)) { 29 | n = length(x) 30 | } 31 | if(n == 0) { 32 | return(newrpqueue) 33 | } 34 | for(i in seq(1,n)) { 35 | el <- peek_front(x) 36 | newrpqueue <- insert_back(newrpqueue, el) 37 | x <- without_front(x) 38 | } 39 | return(newrpqueue) 40 | } -------------------------------------------------------------------------------- /R/head.rstack.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @import utils 3 | #' @title Return the head (top) of an rstack 4 | #' 5 | #' @description Returns the top \eqn{n} elements of an rstack as an stack, or all of the elements 6 | #' if \code{length(x) < n}. 7 | #' 8 | #' @details Runs in \eqn{O(n)} time (in the size of the number of elements requested). 9 | #' @param x rstack to get the head/top of. 10 | #' @param n number of elements to get. 11 | #' @param ... arguments to be passed to or from other methods (ignored). 12 | #' @return an \code{\link{rstack}}. 13 | #' @seealso \code{\link{rstack}}. 14 | #' @examples 15 | #' s <- rstack() 16 | #' s <- insert_top(s, "a") 17 | #' s <- insert_top(s, "b") 18 | #' s <- insert_top(s, "c") 19 | #' 20 | #' st <- head(s, n = 2) 21 | #' print(st) 22 | #' print(s) 23 | head.rstack <- function(x, n = 6L, ...) { 24 | newstack <- rstack() 25 | if(n < 0) { 26 | n = max(n, -1*length(x)) 27 | n = length(x) + n 28 | } 29 | if(n > length(x)) { 30 | n = length(x) 31 | } 32 | if(n == 0 | n < -1*length(x)) { 33 | return(newstack) 34 | } 35 | node <- x$head 36 | for(i in seq(1,n)) { 37 | if(!is.null(node)) { 38 | newstack <- insert_top(newstack, node$data) 39 | node <- node$nextnode 40 | } 41 | } 42 | return(rev(newstack)) 43 | } 44 | 45 | -------------------------------------------------------------------------------- /R/insert_back.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Insert an element into the back of an rdeque or rpqueue 3 | #' 4 | #' @description Returns a version of the deque/queue with the new element in the back position. 5 | #' 6 | #' @details Runs in \eqn{O(1)} time worst-case. Does not modify the original. 7 | #' @param x rdeque or rpqueue to insert onto. 8 | #' @param e element to insert. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return modified version of the rdeque or rpqueue. 11 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 12 | #' @examples 13 | #' d <- rdeque() 14 | #' d <- insert_back(d, "a") 15 | #' d <- insert_back(d, "b") 16 | #' print(d) 17 | #' 18 | #' d2 <- insert_back(d, "c") 19 | #' print(d2) 20 | #' print(d) 21 | insert_back <- function(x, e, ...) {UseMethod("insert_back", x)} -------------------------------------------------------------------------------- /R/insert_back.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Insert an element into the back of an rdeque 3 | #' 4 | #' @description Returns a version of the deque with the new element in the back position. 5 | #' 6 | #' @details Runs in \eqn{O(1)} time worst-case. Does not modify the original. 7 | #' @param x rdeque to insert onto. 8 | #' @param e element to insert. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return modified version of the rdeque. 11 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 12 | #' @examples 13 | #' d <- rdeque() 14 | #' d <- insert_back(d, "a") 15 | #' d <- insert_back(d, "b") 16 | #' print(d) 17 | #' 18 | #' d2 <- insert_back(d, "c") 19 | #' print(d2) 20 | #' print(d) 21 | insert_back.rdeque <- function(x, e, ...) { 22 | newd <- rdeque() 23 | newd$r <- insert_top(x$r, e) 24 | newd$l <- x$l 25 | newd <- fixd(newd) 26 | return(newd) 27 | } 28 | 29 | -------------------------------------------------------------------------------- /R/insert_back.rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Insert an element into the back of an rpqueue 3 | #' 4 | #' @description Returns a version of the queue with the new element in the back position. 5 | #' 6 | #' @details Runs in \eqn{O(1)} time worst-case. Does not modify the original. 7 | #' @param x rpqueue to insert onto. 8 | #' @param e element to insert. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return modified version of the rpqueue. 11 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 12 | #' @examples 13 | #' q <- rpqueue() 14 | #' q <- insert_back(q, "a") 15 | #' q <- insert_back(q, "b") 16 | #' print(q) 17 | #' 18 | #' q2 <- insert_back(q, "c") 19 | #' print(q2) 20 | #' print(q) 21 | insert_back.rpqueue <- function(x, e, ...) { 22 | newq <- rpqueue() 23 | newq$l <- x$l 24 | newq$r <- insert_top(x$r, e) 25 | newq$lhat <- x$lhat 26 | return(makeequal(newq)) 27 | } 28 | 29 | -------------------------------------------------------------------------------- /R/insert_front.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Insert an element into the front of an rdeque 3 | #' 4 | #' @description Returns a version of the deque with the new element in the front position. 5 | #' 6 | #' @details Runs in \eqn{O(1)} time worst-case. Does not modify the original rdeque. 7 | #' @param d rdeque to insert onto. 8 | #' @param e element to insert. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return modified version of the rdeque. 11 | #' @seealso \code{\link{without_front}} for removing the front element. 12 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 13 | #' @examples 14 | #' d <- rdeque() 15 | #' d <- insert_front(d, "a") 16 | #' d <- insert_front(d, "b") 17 | #' print(d) 18 | #' 19 | #' d2 <- insert_front(d, "c") 20 | #' print(d2) 21 | #' print(d) 22 | insert_front <- function(d, e, ...) {UseMethod("insert_front", d)} -------------------------------------------------------------------------------- /R/insert_front.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Insert an element into the front of an rdeque 3 | #' 4 | #' @description Returns a version of the deque with the new element in the front position. 5 | #' 6 | #' @details Runs in \eqn{O(1)} time worst-case. Does not modify the original rdeque. 7 | #' @param d rdeque to insert onto. 8 | #' @param e element to insert. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return modified version of the rdeque. 11 | #' @seealso \code{\link{without_front}} for removing the front element. 12 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 13 | #' @examples 14 | #' d <- rdeque() 15 | #' d <- insert_front(d, "a") 16 | #' d <- insert_front(d, "b") 17 | #' print(d) 18 | #' 19 | #' d2 <- insert_front(d, "c") 20 | #' print(d2) 21 | #' print(d) 22 | insert_front.rdeque <- function(d, e, ...) { 23 | newd <- rdeque() 24 | newd$l <- insert_top(d$l, e) 25 | newd$r <- d$r 26 | newd <- fixd(newd) 27 | return(newd) 28 | } -------------------------------------------------------------------------------- /R/insert_top.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Insert an element onto the top of an rstack 3 | #' 4 | #' @description Insert an element onto the top of an rstack. 5 | #' 6 | #' @details Runs in \eqn{O(1)} time worst-case. Does not semantically modify the original structure (i.e, this 7 | #' function is "pure"). 8 | #' @param s rstack to insert onto. 9 | #' @param e element to insert. 10 | #' @param ... additional arguments to be passed to or from methods (ignored). 11 | #' @return modified version of the stack with new element at top. 12 | #' @seealso \code{\link{rstack}} for information on rstacks, \code{\link{without_top}} for removal of top elements. 13 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 14 | #' @examples 15 | #' s <- rstack() 16 | #' s <- insert_top(s, "a") 17 | #' s <- insert_top(s, "b") 18 | #' print(s) 19 | #' 20 | #' s2 <- insert_top(s, "c") 21 | #' print(s2) 22 | #' print(s) 23 | insert_top <- function(s, e, ...) { UseMethod("insert_top", s) } 24 | 25 | -------------------------------------------------------------------------------- /R/insert_top.rstack.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Insert an element onto the top of an rstack 3 | #' 4 | #' @description Insert an element onto the top of an rstack. 5 | #' 6 | #' @details Runs in \eqn{O(1)} time worst-case. Does not semantically modify the original structure (i.e, this 7 | #' function is "pure"). 8 | #' @param s rstack to insert onto. 9 | #' @param e element to insert. 10 | #' @param ... additional arguments to be passed to or from methods (ignored). 11 | #' @return modified version of the stack with new element at top. 12 | #' @seealso \code{\link{rstack}} for information on rstacks, \code{\link{without_top}} for removal of top elements. 13 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 14 | #' @examples 15 | #' s <- rstack() 16 | #' s <- insert_top(s, "a") 17 | #' s <- insert_top(s, "b") 18 | #' print(s) 19 | #' 20 | #' s2 <- insert_top(s, "c") 21 | #' print(s2) 22 | #' print(s) 23 | insert_top.rstack <- function(s, e, ...) { 24 | newnode <- rstacknode(e) 25 | newstack <- rstack() 26 | newstack$len <- s$len + 1 27 | newnode$nextnode <- s$head 28 | newstack$head <- newnode 29 | return(newstack) 30 | } 31 | 32 | -------------------------------------------------------------------------------- /R/length.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return the number of elements in an rdeque 3 | #' 4 | #' @description Returns the number of elements in an rdeque. 5 | #' 6 | #' @details Runs in \eqn{O(1)} time, as this information is stored seperately and updated on every insert/remove. 7 | #' @param x rdeque to get the length of. 8 | #' @return a vector of length 1 with the number of elements. 9 | #' @seealso \code{\link{empty}} for checking whether an rdeque is empty. 10 | #' @examples 11 | #' d <- rdeque() 12 | #' d <- insert_front(d, "a") 13 | #' print(length(d)) # 1 14 | #' d <- insert_back(d, "b") 15 | #' print(length(d)) # 2 16 | #' @export 17 | length.rdeque <- function(x) { 18 | return(x$l$len + x$r$len) 19 | } -------------------------------------------------------------------------------- /R/length.rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return the number of elements in an rpqueue 3 | #' 4 | #' @description Returns the number of elements in an rpqueue. 5 | #' 6 | #' @details Runs in \eqn{O(1)} time, as this information is stored seperately and updated on every insert/remove. 7 | #' @param x rpqueue to get the length of. 8 | #' @return a vector of length 1 with the number of elements. 9 | #' @seealso \code{\link{empty}} for checking whether an rpqueue is empty. 10 | #' @examples 11 | #' q <- rpqueue() 12 | #' q <- insert_back(q, "a") 13 | #' print(length(q)) # 1 14 | #' q <- insert_back(q, "b") 15 | #' print(length(q)) # 2 16 | #' @export 17 | length.rpqueue <- function(x) { 18 | return(length(x$l) + length(x$r)) 19 | } -------------------------------------------------------------------------------- /R/length.rstack.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return the number of elements in an rstack 3 | #' 4 | #' @description Returns the number of elements in an rstack. 5 | #' 6 | #' @details Runs in \eqn{O(1)} time, as this information is stored seperately and updated on every insert/remove. 7 | #' @param x rstack to get the length of. 8 | #' @return a vector of length 1, which the number of elements of the stack. 9 | #' @seealso \code{\link{empty}} for checking whether an rstack is empty. 10 | #' @examples 11 | #' s <- rstack() 12 | #' s <- insert_top(s, "a") 13 | #' print(length(s)) # 1 14 | #' s <- insert_top(s, "b") 15 | #' print(length(s)) # 2 16 | length.rstack <- function(x) { 17 | return(x$len) 18 | } -------------------------------------------------------------------------------- /R/makeequal.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Generic maintenance function for rpqueues 3 | #' @description Generic maintenance function for rpqueues, called automatically when needed by other functions. 4 | #' @details See \emph{Simple and Efficient Purely Functional Queues and Deques}, 5 | #' Okasaki 1995, J. Functional Programming, 5(4) 583 to 592 for information. 6 | #' @param rpqueue rpqueue to makeequal. 7 | #' @param ... additional arguments to be passed to or from methods (ignored). 8 | #' @return a "fixed" rpqueue. 9 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 10 | #' @seealso \code{\link{rotate}} helper function that calls this one. 11 | makeequal <- function(rpqueue, ...) {UseMethod("makeequal", rpqueue)} 12 | 13 | -------------------------------------------------------------------------------- /R/makeequal.rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Maintenance function for rpqueues 3 | #' @description Maintenance function for rpqueues, called automatically when needed by other functions. 4 | #' @details See \emph{Simple and Efficient Purely Functional Queues and Deques}, 5 | #' Okasaki 1995, J. Functional Programming, 5(4) 583 to 592 for information. 6 | #' @param rpqueue rpqueue to makeequal. 7 | #' @param ... additional arguments to be passed to or from methods (ignored). 8 | #' @return a "fixed" rpqueue. 9 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 10 | #' @seealso \code{\link{rotate}} helper function that calls this one. 11 | makeequal.rpqueue <- function(rpqueue, ...) { 12 | #print(paste(length(rpqueue$lhat, length(rpqueue$l), length(rpqueue$r)))) 13 | if(length(rpqueue$lhat) > 0) { 14 | # maybe here we can avoid creating a whole new object? 15 | newq <- rpqueue() 16 | newq$l <- rpqueue$l 17 | newq$r <- rpqueue$r 18 | newq$lhat <- without_top(rpqueue$lhat) 19 | return(newq) 20 | } else { 21 | newq <- rpqueue() 22 | acc <- rstack() 23 | resq <- rotate(rpqueue, acc) 24 | newq$l <- resq$l 25 | newq$lhat <- resq$l 26 | newq$r <- rstack() 27 | return(newq) 28 | } 29 | } -------------------------------------------------------------------------------- /R/peek_back-set.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Assign to/modify the back of an rdeque 3 | #' 4 | #' @description Allows modification access to the back of a deque. 5 | #' 6 | #' @details Runs in \eqn{O(1)} worst case time. Throws an error if the deque is empty. 7 | #' @param d rdeque to modify the back element of. 8 | #' @param value value to assign to the back data element. 9 | #' @param ... additional arguments to be passed to or from methods. 10 | #' @return modified rdeque. 11 | #' @seealso \code{\link{peek_back.rdeque}} for accessing the back element. 12 | #' @examples 13 | #' d <- rdeque() 14 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 15 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 16 | #' 17 | #' peek_back(d)$a <- 100 18 | #' print(d) 19 | #' 20 | #' peek_back(d) <- data.frame(a = 100, b = 100) 21 | `peek_back<-` <- function(d, ..., value) { UseMethod("peek_back<-", d) } -------------------------------------------------------------------------------- /R/peek_back-set.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Assign to/modify the back of an rdeque 3 | #' 4 | #' @description Allows modification access to the back of a deque. 5 | #' 6 | #' @details Runs in \eqn{O(1)} worst case time. Throws an error if the deque is empty. 7 | #' @param d rdeque to modify the back element of. 8 | #' @param value value to assign to the back data element. 9 | #' @param ... additional arguments to be passed to or from methods. 10 | #' @return modified rdeque. 11 | #' @seealso \code{\link{peek_back.rdeque}} for accessing the back element. 12 | #' @examples 13 | #' d <- rdeque() 14 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 15 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 16 | #' 17 | #' peek_back(d)$a <- 100 18 | #' print(d) 19 | #' 20 | #' peek_back(d) <- data.frame(a = 100, b = 100) 21 | `peek_back<-.rdeque` <- function(d, ..., value) { 22 | if(length(d) < 1) { 23 | stop("cannot assign to the back of an empty deque, try checking with empty() first") 24 | } 25 | d$r$head$data <- value 26 | return(d) 27 | } -------------------------------------------------------------------------------- /R/peek_back.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return the data element at the back of an rdeque 3 | #' 4 | #' @description Simply returns the data element sitting at the back of the rdeque, 5 | #' leaving the rdeque alone. 6 | #' 7 | #' @details Runs in \code{O(1)} worst-case time. 8 | #' @param d rdeque to peek at. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return data element existing at the back of the rdeque. 11 | #' @seealso \code{\link{without_back}} for removing the front element. 12 | #' @examples 13 | #' d <- rdeque() 14 | #' d <- insert_front(d, "a") 15 | #' d <- insert_front(d, "b") 16 | #' e <- peek_back(d) 17 | #' print(e) 18 | #' print(d) 19 | #' 20 | #' ## Assigning to the front data element with peek_front: 21 | #' d <- rdeque() 22 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 23 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 24 | #' 25 | #' peek_back(d)$a <- 100 26 | #' print(d) 27 | #' 28 | #' peek_back(d) <- data.frame(a = 100, b = 100) 29 | #' print(d) 30 | peek_back <- function(d, ...) {UseMethod("peek_back", d)} -------------------------------------------------------------------------------- /R/peek_back.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return the data element at the back of an rdeque 3 | #' 4 | #' @description Simply returns the data element sitting at the back of the rdeque, 5 | #' leaving the rdeque alone. 6 | #' 7 | #' @details Runs in \code{O(1)} worst-case time. 8 | #' @param d rdeque to peek at. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return data element existing at the back of the rdeque. 11 | #' @seealso \code{\link{without_back}} for removing the front element. 12 | #' @examples 13 | #' d <- rdeque() 14 | #' d <- insert_front(d, "a") 15 | #' d <- insert_front(d, "b") 16 | #' e <- peek_back(d) 17 | #' print(e) 18 | #' print(d) 19 | #' 20 | #' ## Assigning to the front data element with peek_front: 21 | #' d <- rdeque() 22 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 23 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 24 | #' 25 | #' peek_back(d)$a <- 100 26 | #' print(d) 27 | #' 28 | #' peek_back(d) <- data.frame(a = 100, b = 100) 29 | #' print(d) 30 | peek_back.rdeque <- function(d, ...) { 31 | if(length(d) < 1) { 32 | stop("cannot peek_back() into a queue that is empty, try checking with empty() first") 33 | } 34 | if(length(d$r) > 0) { 35 | return(peek_top(d$r)) 36 | # invariant: if r is empty but the deque is not, l has only one element 37 | } else { 38 | return(peek_top(d$l)) 39 | } 40 | } 41 | 42 | 43 | -------------------------------------------------------------------------------- /R/peek_front-set.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Assign to/modify the front of an rdeque or rpqueue 3 | #' 4 | #' @description Allows modification access to the front of a deque or queue. 5 | #' 6 | #' @details Runs in \eqn{O(1)} worst case time. Throws an error if the deque is empty. 7 | #' @param x rdeque or rpqueue to modify the front element of. 8 | #' @param value value to assign to the front data element. 9 | #' @param ... additional arguments to be passed to or from methods. 10 | #' @return modified rdeque or rpqueue. 11 | #' @examples 12 | #' d <- rdeque() 13 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 14 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 15 | #' 16 | #' peek_front(d)$a <- 100 17 | #' print(d) 18 | #' 19 | #' peek_front(d) <- data.frame(a = 100, b = 100) 20 | #' 21 | #' 22 | #' 23 | #' q <- rpqueue() 24 | #' q <- insert_front(d, data.frame(a = 1, b = 1)) 25 | #' q <- insert_front(d, data.frame(a = 1, b = 1)) 26 | #' 27 | #' peek_front(q)$a <- 100 28 | #' print(q) 29 | #' 30 | #' peek_front(q) <- data.frame(a = 100, b = 100) 31 | `peek_front<-` <- function(x, ..., value) { UseMethod("peek_front<-", x) } -------------------------------------------------------------------------------- /R/peek_front-set.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Assign to/modify the front of an rdeque 3 | #' 4 | #' @description Allows modification access to the front of a deque. 5 | #' 6 | #' @details Runs in \eqn{O(1)} worst case time. Throws an error if the rdeque is \code{\link{empty}}. Modifies the element in place (i.e., is not side-effect-free). 7 | #' @param x rdeque to modify the front element of. 8 | #' @param value value to assign to the front data element. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return modified rdeque. 11 | #' @seealso \code{\link{peek_front.rdeque}} for accessing the front data element. 12 | #' @examples 13 | #' d <- rdeque() 14 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 15 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 16 | #' 17 | #' peek_front(d)$a <- 100 18 | #' print(d) 19 | #' 20 | #' peek_front(d) <- data.frame(a = 100, b = 100) 21 | #' print(d) 22 | `peek_front<-.rdeque` <- function(x, ..., value) { 23 | if(length(x) < 1) { 24 | stop("cannot assign to the front of an empty deque, try checking with empty() first") 25 | } 26 | x$l$head$data <- value 27 | return(x) 28 | } -------------------------------------------------------------------------------- /R/peek_front-set.rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Assign to/modify the front of an rpqueue 3 | #' 4 | #' @description Allows modification access to the front of a queue. 5 | #' 6 | #' @details Runs in \eqn{O(1)} worst case time. Throws an error if the rpqueue is \code{\link{empty}}. Modifies the element in place (i.e., is not side-effect-free). 7 | #' @param x rpqueue to modify the front element of. 8 | #' @param value value to assign to the front data element. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return modified rpqueue. 11 | #' @seealso \code{\link{peek_front.rpqueue}} for accessing the front data element. 12 | #' @examples 13 | #' q <- rpqueue() 14 | #' q <- insert_back(q, data.frame(a = 1, b = 1)) 15 | #' q <- insert_back(q, data.frame(a = 1, b = 1)) 16 | #' 17 | #' peek_front(q)$a <- 100 18 | #' print(q) 19 | #' 20 | #' peek_front(q) <- data.frame(a = 100, b = 100) 21 | #' print(q) 22 | `peek_front<-.rpqueue` <- function(x, ..., value) { 23 | if(length(x) < 1) { 24 | stop("cannot assign to the front of an empty deque or queue, try checking with empty() first") 25 | } 26 | 27 | if(length(x$l) > 0) { 28 | peek_top(x$l, ...) <- value 29 | # invariant: if l is empty but the deque is not, r has only one element 30 | } else { 31 | peek_top(x$r, ...) <- value 32 | } 33 | 34 | return(x) 35 | } 36 | 37 | -------------------------------------------------------------------------------- /R/peek_front.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return the data element at the front of an rdeque 3 | #' 4 | #' @description Simply returns the data element sitting at the front of the deque, 5 | #' leaving the deque alone. 6 | #' 7 | #' @details Runs in \eqn{O(1)} worst-case time. 8 | #' @param x rdeque to look at. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return data element at the front of the rdeque. 11 | #' @examples 12 | #' d <- rdeque() 13 | #' d <- insert_front(d, "a") 14 | #' d <- insert_back(d, "b") 15 | #' e <- peek_front(d) 16 | #' print(e) 17 | #' print(d) 18 | peek_front <- function(x, ...) {UseMethod("peek_front", x)} 19 | 20 | -------------------------------------------------------------------------------- /R/peek_front.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return the data element at the front of an rdeque 3 | #' 4 | #' @description Simply returns the data element sitting at the front of the rdeque, 5 | #' leaving the rdeque alone. 6 | #' 7 | #' @details Runs in \code{O(1)} worst-case time. 8 | #' @param x rdeque to peek at. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return data element existing at the front of the rdeque. 11 | #' @seealso \code{\link{without_front}} for removing the front element. 12 | #' @examples 13 | #' d <- rdeque() 14 | #' d <- insert_front(d, "a") 15 | #' d <- insert_front(d, "b") 16 | #' e <- peek_front(d) 17 | #' print(e) 18 | #' print(d) 19 | #' 20 | #' ## Assigning to the front data element with peek_front: 21 | #' d <- rdeque() 22 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 23 | #' d <- insert_front(d, data.frame(a = 1, b = 1)) 24 | #' 25 | #' peek_front(d)$a <- 100 26 | #' print(d) 27 | #' 28 | #' peek_front(d) <- data.frame(a = 100, b = 100) 29 | #' print(d) 30 | peek_front.rdeque <- function(x, ...) { 31 | if(length(x) < 1) { 32 | stop("cannot peek_front() into a queue that is empty, try checking with empty() first") 33 | } 34 | if(length(x$l) > 0) { 35 | return(peek_top(x$l)) 36 | # invariant: if l is empty but the deque is not, r has only one element 37 | } else { 38 | return(peek_top(x$r)) 39 | } 40 | } -------------------------------------------------------------------------------- /R/peek_front.rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return the data element at the front of an rpqueue 3 | #' 4 | #' @description Simply returns the data element sitting at the front of the rpqueue, 5 | #' leaving the queue alone. 6 | #' 7 | #' @details Runs in \code{O(1)} worst-case time. 8 | #' @param x rpqueue to peek at. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return data element existing at the front of the queue. 11 | #' @seealso \code{\link{without_front}} for removing the front element. 12 | #' @examples 13 | #' q <- rpqueue() 14 | #' q <- insert_back(q, "a") 15 | #' q <- insert_back(q, "b") 16 | #' e <- peek_front(q) 17 | #' print(e) 18 | #' print(q) 19 | #' 20 | #' ## Assigning to the front data element with peek_front: 21 | #' q <- rpqueue() 22 | #' q <- insert_back(q, data.frame(a = 1, b = 1)) 23 | #' q <- insert_back(q, data.frame(a = 1, b = 1)) 24 | #' 25 | #' peek_front(q)$a <- 100 26 | #' print(q) 27 | #' 28 | #' peek_front(q) <- data.frame(a = 100, b = 100) 29 | #' print(q) 30 | peek_front.rpqueue <- function(x, ...) { 31 | if(length(x) < 1) { 32 | stop("cannot peek_front() into a queue that is empty, try checking with empty() first") 33 | } 34 | if(length(x$l) > 0) { 35 | return(peek_top(x$l)) 36 | # invariant: if l is empty but the deque is not, r has only one element 37 | } else { 38 | return(peek_top(x$r)) 39 | } 40 | } -------------------------------------------------------------------------------- /R/peek_top-set.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Assign to/modify the top of an rstack 3 | #' 4 | #' @description Allows modification access to the top of a stack. 5 | #' 6 | #' @details Runs in \eqn{O(1)} worst case time. Throws an error if the rstack is \code{\link{empty}}. Modifies the element in place (i.e., is not side-effect-free). 7 | #' @param s rstack to modify the first element of. 8 | #' @param value value to assign to the top data element. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return modified rstack. 11 | #' @seealso \code{\link{peek_top}} for accessing the top data element. 12 | #' @examples 13 | #' s <- rstack() 14 | #' s <- insert_top(s, data.frame(a = 1, b = 1)) 15 | #' s <- insert_top(s, data.frame(a = 1, b = 1)) 16 | #' 17 | #' peek_top(s)$a <- 100 18 | #' print(s) 19 | #' 20 | #' peek_top(s) <- data.frame(a = 100, b = 100) 21 | `peek_top<-` <- function(s, ..., value) { UseMethod("peek_top<-", s) } -------------------------------------------------------------------------------- /R/peek_top-set.rstack.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Assign to/modify the top of an rstack 3 | #' 4 | #' @description Allows modification access to the top of a stack. 5 | #' 6 | #' @details Runs in \eqn{O(1)} worst case time. Throws an error if the rstack is \code{\link{empty}}. Modifies the element in place (i.e., is not side-effect-free). 7 | #' @param s rstack to modify the first element of. 8 | #' @param value value to assign to the top data element. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return modified rstack. 11 | #' @seealso \code{\link{peek_top}} for accessing the top data element. 12 | #' @examples 13 | #' s <- rstack() 14 | #' s <- insert_top(s, data.frame(a = 1, b = 1)) 15 | #' s <- insert_top(s, data.frame(a = 1, b = 1)) 16 | #' 17 | #' peek_top(s)$a <- 100 18 | #' print(s) 19 | #' 20 | #' peek_top(s) <- data.frame(a = 100, b = 100) 21 | `peek_top<-.rstack` <- function(s, ..., value) { 22 | if(length(s) < 1) { 23 | stop("cannot assign to the top of an empty stack, try checking with empty() first") 24 | } 25 | s$head$data <- value 26 | return(s) 27 | } -------------------------------------------------------------------------------- /R/peek_top.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return the data element at the top of an rstack 3 | #' 4 | #' @description Simply returns the data element sitting at the top of the rstack, 5 | #' leaving the rstack alone. 6 | #' 7 | #' @details Runs in \code{O(1)} worst-case time. 8 | #' @param s rstack to peek at. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return data element existing at the top of the rstack. 11 | #' @seealso \code{\link{without_top}} for removing the top element. 12 | #' @examples 13 | #' s <- rstack() 14 | #' s <- insert_top(s, "a") 15 | #' s <- insert_top(s, "b") 16 | #' e <- peek_top(s) 17 | #' print(e) 18 | #' print(s) 19 | #' 20 | #' ## Assigning to the top data element with peek_top: 21 | #' s <- rstack() 22 | #' s <- insert_top(s, data.frame(a = 1, b = 1)) 23 | #' s <- insert_top(s, data.frame(a = 1, b = 1)) 24 | #' 25 | #' peek_top(s)$a <- 100 26 | #' print(s) 27 | #' 28 | #' peek_top(s) <- data.frame(a = 100, b = 100) 29 | peek_top <- function(s, ...) { UseMethod("peek_top", s) } -------------------------------------------------------------------------------- /R/peek_top.rstack.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return the data element at the top of an rstack 3 | #' 4 | #' @description Simply returns the data element sitting at the top of the rstack, 5 | #' leaving the rstack alone. 6 | #' 7 | #' @details Runs in \code{O(1)} worst-case time. 8 | #' @param s rstack to peek at. 9 | #' @param ... additional arguments to be passed to or from methods (ignored). 10 | #' @return data element existing at the top of the rstack. 11 | #' @seealso \code{\link{without_top}} for removing the top element. 12 | #' @examples 13 | #' s <- rstack() 14 | #' s <- insert_top(s, "a") 15 | #' s <- insert_top(s, "b") 16 | #' e <- peek_top(s) 17 | #' print(e) 18 | #' print(s) 19 | #' 20 | #' ## Assigning to the top data element with peek_top: 21 | #' s <- rstack() 22 | #' s <- insert_top(s, data.frame(a = 1, b = 1)) 23 | #' s <- insert_top(s, data.frame(a = 1, b = 1)) 24 | #' 25 | #' peek_top(s)$a <- 100 26 | #' print(s) 27 | #' 28 | #' peek_top(s) <- data.frame(a = 100, b = 100) 29 | peek_top.rstack <- function(s, ...) { 30 | if(is.null(s$head)) { 31 | stop("cannot peek() at the top of an empty stack, try checking with empty() first") 32 | } else { 33 | return(s$head$data) 34 | } 35 | } -------------------------------------------------------------------------------- /R/print.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Print an rdeque 3 | #' @description Prints a summary of the contents of an rdeque, including the number of elements and the first and last few. 4 | #' @details Depending on the internal state of the rdeque, this method is not gauranteed to run in \eqn{O(1)} time. 5 | #' @param x the rdeque to print. 6 | #' @param ... additional arguments to be passed to or from methods (ignored). 7 | #' @seealso \code{\link{as.list.rdeque}} for converting an rdeque into a list which can then be printed in full. 8 | print.rdeque <- function(x, ...) { 9 | d <- x 10 | cat(paste("A deque with ", length(d), " elements.\n")) 11 | if(length(d) > 0) { 12 | cat(paste("Front to back: \n")) 13 | } 14 | if(length(d$l) > 0) { 15 | str(as.list(head(d$l, 6)), comp.str = "$", no.list = T) 16 | } 17 | if(length(d) > 12) { 18 | cat(" ...\n") 19 | } 20 | if(length(d$r) > 0) { 21 | str(rev(as.list(head(d$r, 6))), comp.str = "$", no.list = T) 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /R/print.rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Print an rpqueue 3 | #' @description Prints a summary of the contents of an rpqueue, including the number of elements and the first few. 4 | #' @details Since only the first few elements are detailed, runs in \eqn{O(1)} time. 5 | #' @param x the rpqueue to print. 6 | #' @param ... additional arguments to be passed to or from methods (ignored). 7 | #' @seealso \code{\link{as.list.rpqueue}} for converting an rpqueue into a list which can then be printed in full. 8 | print.rpqueue <- function(x, ...) { 9 | cat(paste("A queue with ", length(x), " elements.\n")) 10 | if(length(x) > 0) { 11 | cat(paste("Front: \n")) 12 | } 13 | if(length(x) > 0) { 14 | str(as.list(head(x, 6)), comp.str = "$", no.list = T) 15 | } 16 | } -------------------------------------------------------------------------------- /R/print.rstack.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Print an rstack 3 | #' @description Prints a summary of the contents of an rstack, including the number of elements and the top few. 4 | #' @details Since only the top few elements are detailed, runs in \eqn{O(1)} time. 5 | #' @param x the rstack to print. 6 | #' @param ... additional arguments to be passed to or from methods (ignored). 7 | #' @seealso \code{\link{as.list.rstack}} for converting an rstack into a list which can then be printed in full. 8 | print.rstack <- function(x, ...) { 9 | s <- x 10 | cat(paste("An rstack with ", length(s), " elements. \n")) 11 | if(length(s) > 0) { 12 | if(length(s) > 6) { 13 | cat("Top of the stack:\n") 14 | str(as.list(head(s, 6)), comp.str = " ", no.list = T) 15 | cat(" ...") 16 | } else { 17 | str(as.list(head(s, length(s))), comp.str = "", no.list = T) 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /R/rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Create a new empty rdeque 3 | #' 4 | #' @description Creates a new, empty, rdeque ready for use. 5 | #' 6 | #' @return a new empty rdeque. 7 | #' @details An rdeque provided both "Last In, First Out" (LIFO) and "First In, First Out" (FIFO) access; 8 | #' envisaged as queue, elements may be added or removed from the front or the back with \code{\link{insert_front}}, 9 | #' \code{\link{insert_back}}, \code{\link{without_front}}, and \code{\link{without_back}}. The front and back 10 | #' elements may be retrieved with \code{\link{peek_front}} and \code{\link{peek_back}}. 11 | #' 12 | #' Internally, rdeques are stored as a pair of rstacks; they provide \eqn{O(1)}-amortized insertion and removal, 13 | #' so long as they are not used persistently (that is, the variable storing the deque is always replaced 14 | #' by the modified version, e.g. \code{s <- without_front(s)}). When used persistently (e.g. \code{s2 <- without_front(s)}, which results 15 | #' in two deques being accessible), this cannot be gauranteed. When an \eqn{O(1)} worst-cast, fully 16 | #' persistent FIFO queue is needed, the rpqueue from this package provides these semantics. However, 17 | #' there is a constant-time overhead for rpqueues, such that rdeques are often more efficient (and flexible) 18 | #' in practice, even in when used persistently. 19 | #' 20 | #' Other useful functions 21 | #' include \code{as.list} and \code{as.data.frame} (the latter of which requires that 22 | #' all elements can be appended to become rows of a data frame in a reasonable manner). 23 | #' @seealso \code{\link{rstack}} for a fast LIFO-only structure. 24 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 25 | #' @examples 26 | #' d <- rdeque() 27 | #' d <- insert_front(d, "a") 28 | #' d <- insert_front(d, "b") 29 | #' d <- insert_back(d, "c") 30 | #' d <- insert_back(d, "d") 31 | #' print(d) 32 | #' 33 | #' d2 <- without_back(d) 34 | #' print(d2) 35 | #' print(d) 36 | #' 37 | #' b <- peek_front(d) 38 | #' print(b) 39 | #' @export 40 | rdeque <- function() { 41 | d <- new.env(parent = emptyenv()) 42 | d$l <- rstack() 43 | d$r <- rstack() 44 | class(d) <- "rdeque" 45 | return(d) 46 | } -------------------------------------------------------------------------------- /R/rev.rstack.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Reverse an rstack 3 | #' 4 | #' @description Returns a reversed version of an rstack, where the old last element (generally 5 | #' inaccessible) is now the top (and thus now accessible). 6 | #' 7 | #' @details This method runs in \eqn{O(N)} in the size of the rstack, though it works behind-the-scenes 8 | #' for efficiency by converting the input stack 9 | #' to a list, reversing the list, and building the result as a new rstack. The original is thus 10 | #' left alone, preserving \eqn{O(1)} amortized time for the original (assuming the "cost" of reversing 11 | #' is charged to the newly created stack) at the cost of additional memory usage. But, 12 | #' if the stack is not being used in a preserved manner, e.g. \code{s <- rev(s)}, the garbage collector 13 | #' will be free to clean up the original data if it is no longer usable. 14 | #' @param x rstack to reverse. 15 | #' @return a reversed version of the rstack. 16 | #' @seealso \code{\link{as.list.rstack}} for converting an rstack to a list. 17 | #' @examples 18 | #' s <- rstack() 19 | #' s <- insert_top(s, "a") 20 | #' s <- insert_top(s, "b") 21 | #' s <- insert_top(s, "c") 22 | #' 23 | #' r <- rev(s) 24 | #' print(r) 25 | #' print(s) 26 | rev.rstack <- function(x) { 27 | saslist <- as.list(x) 28 | lastnode <- NULL 29 | for(el in saslist) { 30 | newnode <- rstacknode(el) 31 | newnode$nextnode <- lastnode 32 | lastnode <- newnode 33 | } 34 | newstack <- rstack() 35 | newstack$head <- lastnode 36 | newstack$len <- length(saslist) 37 | return(newstack) 38 | } 39 | 40 | -------------------------------------------------------------------------------- /R/rotate.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Generic maintenance function for rpqueues 3 | #' @description Generic maintenance function for rpqueues, called automatically when needed by other functions. 4 | #' @details See \emph{Simple and Efficient Purely Functional Queues and Deques}, 5 | #' Okasaki 1995, J. Functional Programming, 5(4) 583 to 592 for information. 6 | #' @param rpqueue rpqueue to rotate. 7 | #' @param acclazylist lazy list accumulator. 8 | #' @param ... additional arguments to be passed to or from methods (ignored). 9 | #' @return a fully rotated rpqueue, but with the l list delayed in evaluation. 10 | #' @seealso \code{\link{makeequal}} helper function that calls this one. 11 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 12 | #' @description The lazy list accumulator, keeping the queue partially rotated. 13 | rotate <- function(rpqueue, acclazylist, ...) {UseMethod("rotate", rpqueue)} 14 | 15 | -------------------------------------------------------------------------------- /R/rotate.rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Maintenance function for rpqueues 3 | #' @description Maintenance function for rpqueues, called automatically when needed by other functions. 4 | #' @details See \emph{Simple and Efficient Purely Functional Queues and Deques}, 5 | #' Okasaki 1995, J. Functional Programming, 5(4) 583 to 592 for information on this function. 6 | #' @param rpqueue rpqueue to rotate. 7 | #' @param acclazylist lazy list accumulator. 8 | #' @param ... additional arguments to be passed to or from methods (ignored). 9 | #' @return a fully rotated rpqueue, but with the l list delayed in evaluation. 10 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 11 | #' @seealso \code{\link{makeequal}} helper function that calls this one. 12 | rotate.rpqueue <- function(rpqueue, acclazylist, ...) { 13 | ## safety check :-P 14 | if(length(rpqueue) == 0) { 15 | return(rpqueue) 16 | } 17 | if(length(rpqueue$l) == 0) { 18 | newq <- rpqueue() 19 | newq$l <- rstack() 20 | 21 | newq$l$head <- rstacknode(peek_top(rpqueue$r)) 22 | newq$l$head$nextnode <- acclazylist$head #ie, tail is the lazylist 23 | newq$l$len <- length(rpqueue) + length(acclazylist) 24 | newq$r <- rstack() 25 | return(newq) 26 | } else { 27 | newq <- rpqueue() 28 | newq$l <- rstack() 29 | newq$l$head <- rstacknode(peek_top(rpqueue$l)) 30 | newq$l$len <- length(rpqueue) + length(acclazylist) 31 | 32 | without_heads <- rpqueue() 33 | without_heads$l <- without_top(rpqueue$l) 34 | without_heads$r <- without_top(rpqueue$r) 35 | 36 | acc <- insert_top(acclazylist, peek_top(rpqueue$r)) 37 | delayedAssign("nextnode", rotate(without_heads, acc)$l$head, assign.env = newq$l$head) 38 | newq$r <- rstack() 39 | return(newq) 40 | } 41 | } -------------------------------------------------------------------------------- /R/rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Create a new empty rpqueue 3 | #' 4 | #' @description Creates a new, empty, rpqueue ready for use. 5 | #' 6 | #' @return a new rpqueue. 7 | #' @details An rpqueue provides "First In, First Out" (FIFO) access; envisaged 8 | #' as a queue, elements may be inserted at the back and removed from the front. Unlike 9 | #' \code{\link{rdeque}}, access is gauranteed \eqn{O(1)} worst case even when used 10 | #' persistently, though in most situations rdeques will be faster in practice 11 | #' (see the documentation for \code{\link{rdeque}} for details). 12 | #' 13 | #' Other handy functions 14 | #' include \code{as.list} and \code{as.data.frame} (the latter of which requires that 15 | #' all elements can be appended to become rows of a data frame in a reasonable manner). 16 | #' @seealso \code{\link{rstack}} for a fast LIFO-only structure. 17 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 18 | #' @examples 19 | #' q <- rpqueue() 20 | #' q <- insert_back(q, "a") 21 | #' q <- insert_back(q, "b") 22 | #' print(q) 23 | #' 24 | #' q2 <- without_front(q) 25 | #' print(q2) 26 | #' print(q) 27 | #' 28 | #' b <- peek_front(q) 29 | #' print(b) 30 | rpqueue <- function() { 31 | newq <- new.env(parent = emptyenv()) 32 | newq$lhat <- rstack() 33 | newq$l <- rstack() 34 | newq$r <- rstack() 35 | class(newq) <- "rpqueue" 36 | return(newq) 37 | } -------------------------------------------------------------------------------- /R/rstack.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Create a new, empty rstack 3 | #' 4 | #' @description An rstack is a "Last In, First Out" (LIFO) structure imagined as being organized from 5 | #' top (last in) to bottom (first in), supporting efficient insertion into the 6 | #' top, removal from the top, and peeking/accessing the top element. All functions supported by rstacks are 7 | #' side-effect free. 8 | #' 9 | #' @details Other handy functions supported by rstacks 10 | #' include \code{as.list} and \code{as.data.frame} (the latter of which requires that 11 | #' all elements can be appended to become rows of a data frame in a reasonable manner). Operations 12 | #' are amortized \eqn{O(1)}. 13 | #' 14 | #' The rstack class also supports \code{\link{rev}} - this operation is \eqn{O(N)}, and results in a copy. This 15 | #' means previous versions will retain their \eqn{O(1)} amortized nature (if we assume the cost of the 16 | #' reverse is charged to the newly created stack), at the cost of memory usage. However, this also means 17 | #' that if stacks are used in a non-persistent way, e.g. \code{s <- rev(s)}, then the garbage collector 18 | #' is free to clean up old versions of the data. 19 | #' @seealso \code{\link{insert_top}} for insertion, \code{\link{without_top}} for removal, 20 | #' and \code{\link{peek_top}} for peeking. 21 | #' 22 | #' @return an empty rstack. 23 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 24 | #' @examples 25 | #' s <- rstack() 26 | #' s <- insert_top(s, "a") 27 | #' s <- insert_top(s, "b") 28 | #' print(s) 29 | #' 30 | #' sl <- without_top(s) 31 | #' print(sl) 32 | #' print(s) 33 | #' 34 | #' b <- peek_top(s) 35 | #' print(b) 36 | rstack <- function() { 37 | s <- new.env(parent = emptyenv()) 38 | s$head <- NULL 39 | s$tail <- NULL # for memoization 40 | s$len <- 0 41 | class(s) <- "rstack" 42 | return(s) 43 | } -------------------------------------------------------------------------------- /R/rstacknode.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Internal structure used by rstacks, rdeques, and rpqueues 3 | #' @description 4 | #' For use by rstacks and rdeques. Simply an environment with no parent, 5 | #' reference for the data and the next node. 6 | #' @param data data to reference with this node. 7 | #' @return an environment. 8 | #' 9 | rstacknode <- function(data) { 10 | newnode <- new.env(parent = emptyenv()) 11 | newnode$data <- data 12 | newnode$nextnode <- NULL 13 | class(newnode) <- "rstacknode" 14 | return(newnode) 15 | } -------------------------------------------------------------------------------- /R/without_back.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return a version of an rdeque without the back element 3 | #' 4 | #' @description Simply returns a version of the given rdeque without the back element 5 | #' The original rdeque is left alone. 6 | #' 7 | #' @details Runs in \eqn{O(1)}-amortized time if the rdeque is used non-persistently (see documentation 8 | #' of \code{\link{rdeque}} for details). If the given rdeque is empty, an error will be generated. 9 | #' 10 | #' @param d rdeque to remove elements from. 11 | #' @param ... additional arguments to be passed to or from methods (ignored). 12 | #' @return version of the rdeque with the back element removed. 13 | #' @seealso \code{\link{insert_back}} for inserting elements. 14 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 15 | #' @examples 16 | #' d <- rdeque() 17 | #' d <- insert_front(d, "a") 18 | #' d <- insert_front(d, "b") 19 | #' d <- insert_front(d, "c") 20 | #' 21 | #' d2 <- without_back(d) 22 | #' print(d2) 23 | #' 24 | #' d3 <- without_back(d) 25 | #' print(d3) 26 | #' 27 | #' print(d) 28 | without_back <- function(d, ...) {UseMethod("without_back", d)} -------------------------------------------------------------------------------- /R/without_back.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return a version of an rdeque without the back element 3 | #' 4 | #' @description Simply returns a version of the given rdeque without the back element 5 | #' The original rdeque is left alone. 6 | #' 7 | #' @details Runs in \eqn{O(1)}-amortized time if the rdeque is used non-persistently (see documentation 8 | #' of \code{\link{rdeque}} for details). If the given rdeque is empty, an error will be generated. 9 | #' 10 | #' @param d rdeque to remove elements from. 11 | #' @param ... additional arguments to be passed to or from methods (ignored). 12 | #' @return version of the rdeque with the back element removed. 13 | #' @seealso \code{\link{insert_back}} for inserting elements. 14 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 15 | #' @examples 16 | #' d <- rdeque() 17 | #' d <- insert_front(d, "a") 18 | #' d <- insert_front(d, "b") 19 | #' d <- insert_front(d, "c") 20 | #' 21 | #' d2 <- without_back(d) 22 | #' print(d2) 23 | #' 24 | #' d3 <- without_back(d) 25 | #' print(d3) 26 | #' 27 | #' print(d) 28 | without_back.rdeque <- function(d, ...) { 29 | ## if the length of r is 0, then l has only one element (invariant), so we can return an empty deque 30 | if(length(d$r) == 0) { 31 | return(rdeque()) 32 | } 33 | newd <- rdeque() 34 | newd$l <- d$l 35 | newd$r <- d$r 36 | newd$r <- without_top(newd$r) 37 | newd <- fixd(newd) 38 | return(newd) 39 | } -------------------------------------------------------------------------------- /R/without_front.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return a version of an rdeque or rpqueue without the front element 3 | #' 4 | #' @details Simply returns a version of the given structure without the front element. 5 | #' The original is left alone. 6 | #' 7 | #' @details Runs in \eqn{O(1)}-amortized time for rdeque when used non-persistently (see documentation for 8 | #' \code{\link{rdeque}} for details), \eqn{O(1)} worst-case for rpqueue. Will 9 | #' throw an error if the structure is empty to begin with. 10 | #' 11 | #' @param x rdeque or rpqueue to remove elements from. 12 | #' @param ... additional arguments to be passed to or from methods (ignored). 13 | #' @return a version of the rdeque or rpqueue with the front element removed. 14 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 15 | #' @examples 16 | #' d <- rdeque() 17 | #' d <- insert_front(d, "a") 18 | #' d <- insert_front(d, "b") 19 | #' d <- insert_back(d, "c") 20 | #' 21 | #' d2 <- without_front(d) 22 | #' print(d2) 23 | #' 24 | #' d3 <- without_front(d2) 25 | #' print(d3) 26 | #' 27 | #' print(d) 28 | without_front <- function(x, ...) {UseMethod("without_front", x)} -------------------------------------------------------------------------------- /R/without_front.rdeque.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return a version of an rdeque without the front element 3 | #' 4 | #' @description Simply returns a version of the given rdeque without the front element. Results in an error if the structure is empty. 5 | #' The original rdeque is left alone. 6 | #' 7 | #' @details Runs in \eqn{O(1)}-amortized time if the rdeque is used non-persistently (see documentation 8 | #' of \code{\link{rdeque}} for details). If the given rdeque is empty, an error will be generated. 9 | #' 10 | #' @param x rdeque to remove elements from. 11 | #' @param ... additional arguments to be passed to or from methods (ignored). 12 | #' @return version of the rdeque with the front element removed. 13 | #' @seealso \code{\link{insert_front}} for inserting elements. 14 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 15 | #' @examples 16 | #' d <- rdeque() 17 | #' d <- insert_front(d, "a") 18 | #' d <- insert_front(d, "b") 19 | #' d <- insert_front(d, "c") 20 | #' 21 | #' d2 <- without_front(d) 22 | #' print(d2) 23 | #' 24 | #' d3 <- without_front(d) 25 | #' print(d3) 26 | #' 27 | #' print(d) 28 | without_front.rdeque <- function(x, ...) { 29 | ## if the length of l is 0, then r has only one element (invariant), so we can return an empty deque 30 | if(length(x$l) == 0) { 31 | return(rdeque()) 32 | } 33 | if(length(x) < 1) { 34 | stop("cannot run without_front() on an empty rdeque, check with empty() first") 35 | } 36 | newd <- rdeque() 37 | newd$l <- x$l 38 | newd$r <- x$r 39 | newd$l <- without_top(newd$l) 40 | newd <- fixd(newd) 41 | return(newd) 42 | } 43 | 44 | -------------------------------------------------------------------------------- /R/without_front.rpqueue.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return a version of an rpqueue without the front element 3 | #' 4 | #' @description Simply returns a version of the given rpqueue without the front element. Results in an error if the structure is empty. 5 | #' The original rpqueue is left alone. 6 | #' 7 | #' @details Runs in \eqn{O(1)} worst case time. 8 | #' 9 | #' @param x rpqueue to remove elements from. 10 | #' @param ... additional arguments to be passed to or from methods (ignored). 11 | #' @return version of the rpqueue with the front element removed. 12 | #' @seealso \code{\link{peek_front}} for accessing the front element. 13 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 14 | #' @examples 15 | #' q <- rpqueue() 16 | #' q <- insert_back(q, "a") 17 | #' q <- insert_back(q, "b") 18 | #' q <- insert_back(q, "c") 19 | #' 20 | #' q2 <- without_front(q) 21 | #' print(q2) 22 | #' 23 | #' q3 <- without_front(q) 24 | #' print(q3) 25 | #' 26 | #' print(q) 27 | without_front.rpqueue <- function(x, ...) { 28 | if(length(x) < 1) { 29 | stop("cannot run without_front() on an empty rpqueue, try checking with empty() first") 30 | } 31 | newq <- rpqueue() 32 | newq$l <- without_top(x$l) 33 | newq$r <- x$r 34 | newq$lhat <- x$lhat 35 | return(makeequal(newq)) 36 | } -------------------------------------------------------------------------------- /R/without_top.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return a version of an rstack without the top element 3 | #' 4 | #' @description Simply returns a version of the given stack without the top element. Results in an error if the structure is empty. 5 | #' The original rstack is left alone. 6 | #' 7 | #' @details Runs in \eqn{O(1)} time worst case. 8 | #' 9 | #' @param s rstack to remove elements from. 10 | #' @param ... additional arguments to be passed to or from methods (ignored). 11 | #' @return version of the stack with the top \eqn{n} elements removed. 12 | #' @seealso \code{\link{insert_top}} for inserting elements. 13 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 14 | #' @examples 15 | #' s <- rstack() 16 | #' s <- insert_top(s, "a") 17 | #' s <- insert_top(s, "b") 18 | #' s <- insert_top(s, "c") 19 | #' 20 | #' s2 <- without_top(s) 21 | #' print(s2) 22 | #' 23 | #' print(s) 24 | without_top <- function(s, ...) { UseMethod("without_top", s) } -------------------------------------------------------------------------------- /R/without_top.rstack.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @title Return a version of an rstack without the top element 3 | #' 4 | #' @description Simply returns a version of the given stack without the top element. Results in an error if the structure is empty. 5 | #' The original rstack is left alone. 6 | #' 7 | #' @details Runs in \eqn{O(1)} time worst case. 8 | #' 9 | #' @param s rstack to remove elements from. 10 | #' @param ... additional arguments to be passed to or from methods (ignored). 11 | #' @return version of the stack with the top \eqn{n} elements removed. 12 | #' @seealso \code{\link{insert_top}} for inserting elements. 13 | #' @references Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 14 | #' @examples 15 | #' s <- rstack() 16 | #' s <- insert_top(s, "a") 17 | #' s <- insert_top(s, "b") 18 | #' s <- insert_top(s, "c") 19 | #' 20 | #' s2 <- without_top(s) 21 | #' print(s2) 22 | #' 23 | #' print(s) 24 | without_top.rstack <- function(s, ...) { 25 | n = 1 26 | if(length(s) < n) { 27 | stop("cannot run without_top() on an empty rstack, check with empty() first") 28 | } 29 | ## memozied 30 | if(!is.null(s$tail)) {return(s$tail)} 31 | newstack <- rstack() 32 | node <- s$head 33 | for(i in seq(1,n)) { 34 | node <- node$nextnode 35 | } 36 | newstack$len <- s$len - n 37 | newstack$head <- node 38 | s$tail <- newstack 39 | return(newstack) 40 | } 41 | 42 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "README" 3 | author: "Shawn T O'Neil" 4 | date: "5/1/2022" 5 | output: 6 | html_document: 7 | keep_md: true 8 | --- 9 | 10 | ```{r setup, include=FALSE} 11 | knitr::opts_chunk$set(echo = TRUE) 12 | knitr::opts_chunk$set(fig.path = "README_figs/README-") 13 | ``` 14 | 15 | ## `rstackdeque`: Persistent stacks, deques, and queues for R 16 | 17 | 18 | R journal publication: [https://journal.r-project.org/archive/2015-1/oneil.pdf](https://journal.r-project.org/archive/2015-1/oneil.pdf) 19 | 20 | Have you ever wanted to use a stack or a queue for R, but just pulled your hair out 21 | trying to use lists or vectors instead? Enter rstackdeque. 22 | 23 | The most important feature of the stacks and queues (and double-ended-queues, or 24 | "deques") in this package are not only are they reasonably fast (amortized or 25 | worst-case O(1) depending on which you're using), inserting and removal are 26 | implemented as "side-effect-free" functions operating similar to other R 27 | structures. 28 | 29 | This is largely possible due to the fantastic work of 30 | Chris Okasaki: see [Purely Functional Data Structures](http://www.amazon.com/Purely-Functional-Structures-Chris-Okasaki/dp/0521663504) 31 | and [Simple and Efficient Purely Functional Queues and Deques](http://www.westpoint.edu/eecs/SiteAssets/SitePages/Faculty%20Publication%20Documents/Okasaki/jfp95queue.pdf). 32 | 33 | 34 | *Psst, you can use these to efficiently build a data frame or list in a loop:* 35 | 36 | ```{r warning=FALSE,message=FALSE} 37 | library(rstackdeque) 38 | library(dplyr) 39 | 40 | stack <- rstack() 41 | 42 | for(i in 1:5) { 43 | stack <- stack %>% insert_top(data.frame(i = i, logi = log(i))) 44 | } 45 | 46 | print(as.data.frame(stack)) 47 | ``` 48 | 49 | *See more good stuff under Common Functionality below.* 50 | 51 | 52 | ## Install 53 | 54 | 55 | You can install this package via CRAN: 56 | 57 | ```{r eval=FALSE} 58 | install.packages("rstackdeque") 59 | ``` 60 | 61 | Then load it up and check the help and examples: 62 | 63 | ```{r eval=FALSE} 64 | require(rstackdeque) 65 | help(package = "rstackdeque") 66 | help(rstack) 67 | help(rdeque) 68 | help(rpqueue) 69 | ``` 70 | 71 | ## Quick Start 72 | 73 | 74 | ### Stacks 75 | 76 | An `rstack()` is a stack-like structure, that supports adding elements to the "top": 77 | 78 | ```{r} 79 | library(rstackdeque) 80 | library(dplyr) 81 | 82 | 83 | stack <- rstack() %>% 84 | insert_top("A") %>% 85 | insert_top("B") %>% 86 | insert_top("C") %>% 87 | insert_top("D") 88 | 89 | print(stack) 90 | ``` 91 | 92 | 93 | 94 | They also allow "peeking at" (returning a copy of) the top element. This does not change the contents of the stack. 95 | 96 | ```{r} 97 | top_element <- peek_top(stack) 98 | print(top_element) 99 | ``` 100 | 101 | 102 | Lastly, they support dropping the top element: 103 | 104 | ```{r} 105 | stack <- without_top(stack) 106 | print(stack) 107 | ``` 108 | 109 | 110 | ### Deques (double-ended queues) 111 | 112 | Deques, or double-ended queues, support adding and removing elements to either the "front" or "back" of the queue. 113 | 114 | 115 | ```{r} 116 | deque <- rdeque() %>% 117 | insert_front("A") %>% 118 | insert_front("B") %>% 119 | insert_front("C") %>% 120 | insert_back("X") %>% 121 | insert_back("Y") %>% 122 | insert_back("Z") 123 | 124 | print(deque) 125 | 126 | deque <- without_front(deque) 127 | deque <- without_back(deque) 128 | print(deque) 129 | ``` 130 | The `peek_front()` and `peek_back()` functions return the first and last elements: 131 | 132 | ```{r} 133 | first_el <- peek_front(deque) 134 | last_el <- peek_back(deque) 135 | 136 | print(first_el) 137 | print(last_el) 138 | ``` 139 | 140 | While insertions and removals from `rstack`s are always fast, certain patterns of repeated insertions and removals from an `rdeque` will cause periodic 're-balancing' operations where a full copy of the deque is made with more efficient internal organization. Thus, although `rdeque`s provide more functionality than `rstack`s, `rstack`s are preferred unless deque operations are required. 141 | 142 | ### Queues 143 | 144 | Queues support a subset of functionality of dequeus - queues only allow inserting elements at the back of the queue, and removing elements from the front of the queue. Peeking is also only supported at the front of the queue. 145 | 146 | ```{r} 147 | queue <- rpqueue() %>% 148 | insert_back("A") %>% 149 | insert_back("B") %>% 150 | insert_back("C") 151 | 152 | print(queue) 153 | 154 | queue <- without_front(queue) 155 | print(queue) 156 | 157 | first_el <- peek_front(queue) 158 | print(first_el) 159 | ``` 160 | Queues provide a subset of functionality of deques, but this implementation comes with an efficiency improvement: while `rdeques` may experience 161 | periodic re-balancing described above, `rpqueus` do not, such that insertions and removals always take approximately the same time. The complexity of supporting this for queues, however, makes the implementation slower in practice that `rstack`s. These queues are thus a good choice when queue functionality is needed in real-time applications (e.g. user interfaces). 162 | 163 | 164 | ### Common Functionality 165 | 166 | All three types support `empty()` (`TRUE` or `FALSE`), `length()`, and `head()` (where the head is the front of deques and queues, 167 | and the top of stacks), and `rstacks` also support `rev()` (but this operations makes a full copy). 168 | 169 | We demonstrate features below for `rstack`s, but they also apply to `rdeque`s 170 | and `rpqueue`s (discussed below). 171 | 172 | 173 | #### Element types 174 | 175 | Almost any datatype can be stored - vectors, lists, data.frames, models, etc. 176 | 177 | ```{r} 178 | stuff <- rstack() %>% 179 | insert_top(mtcars) %>% 180 | insert_top(t.test(rnorm(25), rnorm(25))) 181 | 182 | print(stuff) 183 | ``` 184 | 185 | 186 | 187 | #### Conversion to or from lists or vectors 188 | 189 | ```{r} 190 | letters_stack <- as.rstack(letters) 191 | print(letters_stack) 192 | ``` 193 | 194 | 195 | ... and converted to a list. If the list is simple, the R-base `unlist()` 196 | function is handy: 197 | 198 | ```{r} 199 | letters_again <- as.list(letters) %>% unlist() 200 | print(letters_again) 201 | ``` 202 | 203 | 204 | #### Conversion to data.frames 205 | 206 | If the elements are lists that have the same element names in the same order, or dataframes with the 207 | same column names in the same order, they can be converted to a `data.frame`. If elements are data frames, the rows 208 | will be concatenated. 209 | 210 | ```{r} 211 | people_stack <- rstack() %>% 212 | insert_top(list(name = "Joe", age = 26)) %>% 213 | insert_top(list(name = "Kim", age = 30)) 214 | 215 | people_df <- as.data.frame(people_stack) 216 | print(people_df) 217 | ``` 218 | 219 | #### Usage with loops 220 | 221 | As a result, these structures pair nicely with loops. Here's a loop 222 | that computes a [Collatz sequence](https://en.wikipedia.org/wiki/Collatz_conjecture) from a given starting number. 223 | 224 | ```{r} 225 | value <- 17 226 | step <- 1 227 | 228 | collatz_stack <- rstack() 229 | 230 | while(value != 1) { 231 | if(value %% 2 == 0) { 232 | value <- value / 2 233 | } else { 234 | value <- value * 3 + 1 235 | } 236 | 237 | collatz_stack <- collatz_stack %>% insert_top(list(value = value, step = step)) 238 | step <- step + 1 239 | } 240 | 241 | collatz_df <- as.data.frame(collatz_stack) %>% arrange(step) 242 | print(collatz_df) 243 | ``` 244 | 245 | 246 | Note: Although the structures in `rstackdeque` are generally designed to be fast, 247 | for performance-critical applications where the size of the result is known 248 | a-priori, using a [pre-allocation strategy](https://www.r-bloggers.com/2018/08/growing-objects-and-loop-memory-pre-allocation/) will be faster. 249 | Computing the Collatz sequence as shown above is an example where pre-allocation is difficult, and stacks, queues, and deques (double-ended queues) are important components of many algorithms. See Timothy Barry's [Collections in R: Review and Proposal](https://journal.r-project.org/archive/2018/RJ-2018-037/RJ-2018-037.pdf) (R Journal, 10(1), 2018) for a comparison of different R implementations of these and similar data structures. 250 | 251 | #### Persistence 252 | 253 | All of the structures described are *persistent*, meaning that additions and 254 | removals don't alter the original; practically, a modified copy is returned. 255 | (A full copy is not made however, the structures handle efficient organization 256 | of the data in memory.) 257 | 258 | 259 | ```{r} 260 | stack <- as.rstack(c("A", "B", "C")) 261 | stack2 <- insert_top(stack, "G") 262 | stack3 <- without_top(stack) 263 | 264 | print(stack) 265 | print(stack2) 266 | print(stack3) 267 | ``` 268 | This property makes functions that use the structures "side-effect-free" like most R types, supporting pure functions and parallelization. 269 | 270 | 271 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## `rstackdeque`: Persistent stacks, deques, and queues for R 2 | 3 | 4 | R journal publication: [https://journal.r-project.org/archive/2015-1/oneil.pdf](https://journal.r-project.org/archive/2015-1/oneil.pdf) 5 | 6 | Have you ever wanted to use a stack or a queue for R, but just pulled your hair out 7 | trying to use lists or vectors instead? Enter rstackdeque. 8 | 9 | The most important feature of the stacks and queues (and double-ended-queues, or 10 | "deques") in this package are not only are they reasonably fast (amortized or 11 | worst-case O(1) depending on which you're using), inserting and removal are 12 | implemented as "side-effect-free" functions operating similar to other R 13 | structures. 14 | 15 | This is largely possible due to the fantastic work of 16 | Chris Okasaki: see [Purely Functional Data Structures](http://www.amazon.com/Purely-Functional-Structures-Chris-Okasaki/dp/0521663504) 17 | and [Simple and Efficient Purely Functional Queues and Deques](http://www.westpoint.edu/eecs/SiteAssets/SitePages/Faculty%20Publication%20Documents/Okasaki/jfp95queue.pdf). 18 | 19 | - [Install](#install) 20 | - [Quick Start](#quick-start) 21 | * [Stacks](#stacks) 22 | * [Deques (double-ended queues)](#deques--double-ended-queues-) 23 | * [Queues](#queues) 24 | * [Common Functionality](#common-functionality) 25 | + [Element types](#element-types) 26 | + [Conversion to or from lists or vectors](#conversion-to-or-from-lists-or-vectors) 27 | + [Conversion to data.frames](#conversion-to-dataframes) 28 | + [Usage with loops](#usage-with-loops) 29 | + [Persistence](#persistence) 30 | 31 | 32 | 33 | 34 | *Psst, you can use these to efficiently build a data frame or list in a loop:* 35 | 36 | 37 | ```r 38 | library(rstackdeque) 39 | library(dplyr) 40 | 41 | stack <- rstack() 42 | 43 | for(i in 1:5) { 44 | stack <- stack %>% insert_top(data.frame(i = i, logi = log(i))) 45 | } 46 | 47 | print(as.data.frame(stack)) 48 | ``` 49 | 50 | ``` 51 | ## i logi 52 | ## 1 5 1.6094379 53 | ## 2 4 1.3862944 54 | ## 3 3 1.0986123 55 | ## 4 2 0.6931472 56 | ## 5 1 0.0000000 57 | ``` 58 | 59 | *See more good stuff under Common Functionality below.* 60 | 61 | 62 | ## Install 63 | 64 | 65 | You can install this package via CRAN: 66 | 67 | 68 | ```r 69 | install.packages("rstackdeque") 70 | ``` 71 | 72 | Then load it up and check the help and examples: 73 | 74 | 75 | ```r 76 | require(rstackdeque) 77 | help(package = "rstackdeque") 78 | help(rstack) 79 | help(rdeque) 80 | help(rpqueue) 81 | ``` 82 | 83 | ## Quick Start 84 | 85 | 86 | ### Stacks 87 | 88 | An `rstack()` is a stack-like structure, that supports adding elements to the "top": 89 | 90 | 91 | ```r 92 | library(rstackdeque) 93 | library(dplyr) 94 | 95 | 96 | stack <- rstack() %>% 97 | insert_top("A") %>% 98 | insert_top("B") %>% 99 | insert_top("C") %>% 100 | insert_top("D") 101 | 102 | print(stack) 103 | ``` 104 | 105 | ``` 106 | ## An rstack with 4 elements. 107 | ## : chr "D" 108 | ## : chr "C" 109 | ## : chr "B" 110 | ## : chr "A" 111 | ``` 112 | 113 | 114 | 115 | They also allow "peeking at" (returning a copy of) the top element. This does not change the contents of the stack. 116 | 117 | 118 | ```r 119 | top_element <- peek_top(stack) 120 | print(top_element) 121 | ``` 122 | 123 | ``` 124 | ## [1] "D" 125 | ``` 126 | 127 | 128 | Lastly, they support dropping the top element: 129 | 130 | 131 | ```r 132 | stack <- without_top(stack) 133 | print(stack) 134 | ``` 135 | 136 | ``` 137 | ## An rstack with 3 elements. 138 | ## : chr "C" 139 | ## : chr "B" 140 | ## : chr "A" 141 | ``` 142 | 143 | 144 | ### Deques (double-ended queues) 145 | 146 | Deques, or double-ended queues, support adding and removing elements to either the "front" or "back" of the queue. 147 | 148 | 149 | 150 | ```r 151 | deque <- rdeque() %>% 152 | insert_front("A") %>% 153 | insert_front("B") %>% 154 | insert_front("C") %>% 155 | insert_back("X") %>% 156 | insert_back("Y") %>% 157 | insert_back("Z") 158 | 159 | print(deque) 160 | ``` 161 | 162 | ``` 163 | ## A deque with 6 elements. 164 | ## Front to back: 165 | ## $: chr "C" 166 | ## $: chr "B" 167 | ## $: chr "A" 168 | ## $: chr "X" 169 | ## $: chr "Y" 170 | ## $: chr "Z" 171 | ``` 172 | 173 | ```r 174 | deque <- without_front(deque) 175 | deque <- without_back(deque) 176 | print(deque) 177 | ``` 178 | 179 | ``` 180 | ## A deque with 4 elements. 181 | ## Front to back: 182 | ## $: chr "B" 183 | ## $: chr "A" 184 | ## $: chr "X" 185 | ## $: chr "Y" 186 | ``` 187 | The `peek_front()` and `peek_back()` functions return the first and last elements: 188 | 189 | 190 | ```r 191 | first_el <- peek_front(deque) 192 | last_el <- peek_back(deque) 193 | 194 | print(first_el) 195 | ``` 196 | 197 | ``` 198 | ## [1] "B" 199 | ``` 200 | 201 | ```r 202 | print(last_el) 203 | ``` 204 | 205 | ``` 206 | ## [1] "Y" 207 | ``` 208 | 209 | While insertions and removals from `rstack`s are always fast, certain patterns of repeated insertions and removals from an `rdeque` will cause periodic 're-balancing' operations where a full copy of the deque is made with more efficient internal organization. Thus, although `rdeque`s provide more functionality than `rstack`s, `rstack`s are preferred unless deque operations are required. 210 | 211 | ### Queues 212 | 213 | Queues support a subset of functionality of dequeus - queues only allow inserting elements at the back of the queue, and removing elements from the front of the queue. Peeking is also only supported at the front of the queue. 214 | 215 | 216 | ```r 217 | queue <- rpqueue() %>% 218 | insert_back("A") %>% 219 | insert_back("B") %>% 220 | insert_back("C") 221 | 222 | print(queue) 223 | ``` 224 | 225 | ``` 226 | ## A queue with 3 elements. 227 | ## Front: 228 | ## $: chr "A" 229 | ## $: chr "B" 230 | ## $: chr "C" 231 | ``` 232 | 233 | ```r 234 | queue <- without_front(queue) 235 | print(queue) 236 | ``` 237 | 238 | ``` 239 | ## A queue with 2 elements. 240 | ## Front: 241 | ## $: chr "B" 242 | ## $: chr "C" 243 | ``` 244 | 245 | ```r 246 | first_el <- peek_front(queue) 247 | print(first_el) 248 | ``` 249 | 250 | ``` 251 | ## [1] "B" 252 | ``` 253 | Queues provide a subset of functionality of deques, but this implementation comes with an efficiency improvement: while `rdeques` may experience 254 | periodic re-balancing described above, `rpqueus` do not, such that insertions and removals always take approximately the same time. The complexity of supporting this for queues, however, makes the implementation slower in practice that `rstack`s. These queues are thus a good choice when queue functionality is needed in real-time applications (e.g. user interfaces). 255 | 256 | 257 | ### Common Functionality 258 | 259 | All three types support `empty()` (`TRUE` or `FALSE`), `length()`, and `head()` (where the head is the front of deques and queues, 260 | and the top of stacks), and `rstacks` also support `rev()` (but this operations makes a full copy). 261 | 262 | We demonstrate features below for `rstack`s, but they also apply to `rdeque`s 263 | and `rpqueue`s (discussed below). 264 | 265 | 266 | #### Element types 267 | 268 | Almost any datatype can be stored - vectors, lists, data.frames, models, etc. 269 | 270 | 271 | ```r 272 | stuff <- rstack() %>% 273 | insert_top(mtcars) %>% 274 | insert_top(t.test(rnorm(25), rnorm(25))) 275 | 276 | print(stuff) 277 | ``` 278 | 279 | ``` 280 | ## An rstack with 2 elements. 281 | ## :List of 10 282 | ## ..$ statistic : Named num -0.558 283 | ## .. ..- attr(*, "names")= chr "t" 284 | ## ..$ parameter : Named num 47.9 285 | ## .. ..- attr(*, "names")= chr "df" 286 | ## ..$ p.value : num 0.579 287 | ## ..$ conf.int : num [1:2] -0.73 0.413 288 | ## .. ..- attr(*, "conf.level")= num 0.95 289 | ## ..$ estimate : Named num [1:2] -0.356 -0.197 290 | ## .. ..- attr(*, "names")= chr [1:2] "mean of x" "mean of y" 291 | ## ..$ null.value : Named num 0 292 | ## .. ..- attr(*, "names")= chr "difference in means" 293 | ## ..$ stderr : num 0.284 294 | ## ..$ alternative: chr "two.sided" 295 | ## ..$ method : chr "Welch Two Sample t-test" 296 | ## ..$ data.name : chr "rnorm(25) and rnorm(25)" 297 | ## ..- attr(*, "class")= chr "htest" 298 | ## :'data.frame': 32 obs. of 11 variables: 299 | ## ..$ mpg : num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ... 300 | ## ..$ cyl : num [1:32] 6 6 4 6 8 6 8 4 4 6 ... 301 | ## ..$ disp: num [1:32] 160 160 108 258 360 ... 302 | ## ..$ hp : num [1:32] 110 110 93 110 175 105 245 62 95 123 ... 303 | ## ..$ drat: num [1:32] 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ... 304 | ## ..$ wt : num [1:32] 2.62 2.88 2.32 3.21 3.44 ... 305 | ## ..$ qsec: num [1:32] 16.5 17 18.6 19.4 17 ... 306 | ## ..$ vs : num [1:32] 0 0 1 1 0 1 0 1 1 1 ... 307 | ## ..$ am : num [1:32] 1 1 1 0 0 0 0 0 0 0 ... 308 | ## ..$ gear: num [1:32] 4 4 4 3 3 3 3 4 4 4 ... 309 | ## ..$ carb: num [1:32] 4 4 1 1 2 1 4 2 2 4 ... 310 | ``` 311 | 312 | 313 | 314 | #### Conversion to or from lists or vectors 315 | 316 | 317 | ```r 318 | letters_stack <- as.rstack(letters) 319 | print(letters_stack) 320 | ``` 321 | 322 | ``` 323 | ## An rstack with 26 elements. 324 | ## Top of the stack: 325 | ## : chr "a" 326 | ## : chr "b" 327 | ## : chr "c" 328 | ## : chr "d" 329 | ## : chr "e" 330 | ## : chr "f" 331 | ## ... 332 | ``` 333 | 334 | 335 | ... and converted to a list. If the list is simple, the R-base `unlist()` 336 | function is handy: 337 | 338 | 339 | ```r 340 | letters_again <- as.list(letters) %>% unlist() 341 | print(letters_again) 342 | ``` 343 | 344 | ``` 345 | ## [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" 346 | ## [20] "t" "u" "v" "w" "x" "y" "z" 347 | ``` 348 | 349 | 350 | #### Conversion to data.frames 351 | 352 | If the elements are lists that have the same element names in the same order, or dataframes with the 353 | same column names in the same order, they can be converted to a `data.frame`. If elements are data frames, the rows 354 | will be concatenated. 355 | 356 | 357 | ```r 358 | people_stack <- rstack() %>% 359 | insert_top(list(name = "Joe", age = 26)) %>% 360 | insert_top(list(name = "Kim", age = 30)) 361 | 362 | people_df <- as.data.frame(people_stack) 363 | print(people_df) 364 | ``` 365 | 366 | ``` 367 | ## name age 368 | ## 1 Kim 30 369 | ## 2 Joe 26 370 | ``` 371 | 372 | #### Usage with loops 373 | 374 | As a result, these structures pair nicely with loops. Here's a loop 375 | that computes a [Collatz sequence](https://en.wikipedia.org/wiki/Collatz_conjecture) from a given starting number. 376 | 377 | 378 | ```r 379 | value <- 17 380 | step <- 1 381 | 382 | collatz_stack <- rstack() 383 | 384 | while(value != 1) { 385 | if(value %% 2 == 0) { 386 | value <- value / 2 387 | } else { 388 | value <- value * 3 + 1 389 | } 390 | 391 | collatz_stack <- collatz_stack %>% insert_top(list(value = value, step = step)) 392 | step <- step + 1 393 | } 394 | 395 | collatz_df <- as.data.frame(collatz_stack) %>% arrange(step) 396 | print(collatz_df) 397 | ``` 398 | 399 | ``` 400 | ## value step 401 | ## 1 52 1 402 | ## 2 26 2 403 | ## 3 13 3 404 | ## 4 40 4 405 | ## 5 20 5 406 | ## 6 10 6 407 | ## 7 5 7 408 | ## 8 16 8 409 | ## 9 8 9 410 | ## 10 4 10 411 | ## 11 2 11 412 | ## 12 1 12 413 | ``` 414 | 415 | 416 | Note: Although the structures in `rstackdeque` are generally designed to be fast, 417 | for performance-critical applications where the size of the result is known 418 | a-priori, using a [pre-allocation strategy](https://www.r-bloggers.com/2018/08/growing-objects-and-loop-memory-pre-allocation/) will be faster. 419 | Computing the Collatz sequence as shown above is an example where pre-allocation is difficult, and stacks, queues, and deques (double-ended queues) are important components of many algorithms. See Timothy Barry's [Collections in R: Review and Proposal](https://journal.r-project.org/archive/2018/RJ-2018-037/RJ-2018-037.pdf) (R Journal, 10(1), 2018) for a comparison of different R implementations of these and similar data structures. 420 | 421 | #### Persistence 422 | 423 | All of the structures described are *persistent*, meaning that additions and 424 | removals don't alter the original; practically, a modified copy is returned. 425 | (A full copy is not made however, the structures handle efficient organization 426 | of the data in memory.) 427 | 428 | 429 | 430 | ```r 431 | stack <- as.rstack(c("A", "B", "C")) 432 | stack2 <- insert_top(stack, "G") 433 | stack3 <- without_top(stack) 434 | 435 | print(stack) 436 | ``` 437 | 438 | ``` 439 | ## An rstack with 3 elements. 440 | ## : chr "A" 441 | ## : chr "B" 442 | ## : chr "C" 443 | ``` 444 | 445 | ```r 446 | print(stack2) 447 | ``` 448 | 449 | ``` 450 | ## An rstack with 4 elements. 451 | ## : chr "G" 452 | ## : chr "A" 453 | ## : chr "B" 454 | ## : chr "C" 455 | ``` 456 | 457 | ```r 458 | print(stack3) 459 | ``` 460 | 461 | ``` 462 | ## An rstack with 2 elements. 463 | ## : chr "B" 464 | ## : chr "C" 465 | ``` 466 | This property makes functions that use the structures "side-effect-free" like most R types, supporting pure functions and parallelization. 467 | 468 | 469 | -------------------------------------------------------------------------------- /man/as.data.frame.rdeque.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/as.data.frame.rdeque.R 3 | \name{as.data.frame.rdeque} 4 | \alias{as.data.frame.rdeque} 5 | \title{Convert an rdeque to a data.frame} 6 | \usage{ 7 | \method{as.data.frame}{rdeque}(x, row.names = NULL, optional = FALSE, ...) 8 | } 9 | \arguments{ 10 | \item{x}{rdeque to convert.} 11 | 12 | \item{row.names}{passed on to \code{as.data.frame} before final conversion.} 13 | 14 | \item{optional}{passed onto \code{as.data.frame} before final conversion.} 15 | 16 | \item{...}{passed onto \code{as.data.frame} before final conversion.} 17 | } 18 | \value{ 19 | a data.frame with the first row the previous front of the deque and last row the previous back. 20 | } 21 | \description{ 22 | Converts the elements of an rdeque into rows of a data.frame, if this is reasonable. 23 | } 24 | \details{ 25 | This function runs in \eqn{O(N)} time in the size of the rdeque, and will only work if all 26 | elements of the deque have the same \code{length()} (e.g., same number of columns), and if any of the 27 | elements have names, then those names do not conflict (e.g., same column names where used). 28 | This is accomplished by a call to 29 | \code{do.call("rbind", as.list.rdeque(x))}, where \code{\link{as.list.rdeque}} converts the rdeque to a list 30 | where the front element becomes the first element of the list. 31 | } 32 | \examples{ 33 | d <- rdeque() 34 | d <- insert_front(d, data.frame(names = c("Bob", "Joe"), ages = c(25, 18))) 35 | d <- insert_front(d, data.frame(names = c("Mary", "Kate", "Ashley"), ages = c(27, 26, 21))) 36 | print(d) 37 | 38 | dd <- as.data.frame(d) 39 | print(dd) 40 | 41 | ## Elements may be similarly-named lists as well, representing individual rows: 42 | d <- rdeque() 43 | d <- insert_front(d, list(name = "Bob", age = 25)) 44 | d <- insert_front(d, list(name = "Mary", age = 24)) 45 | print(d) 46 | 47 | dd <- as.data.frame(d) 48 | print(dd) 49 | 50 | ## Building a deque in a loop, converting to a dataframe after the fact: 51 | d <- rdeque() 52 | for(i in 1:1000) { 53 | if(runif(1,0,1) < 0.5) { 54 | d <- insert_front(d, data.frame(i = i, type = "sqrt", val = sqrt(i))) 55 | } else { 56 | d <- insert_back(d, data.frame(i = i, type = "log", val = log(i))) 57 | } 58 | if(i \%\% 100 == 0) { 59 | print(i/1000) 60 | } 61 | } 62 | print(head(as.data.frame(d))) 63 | } 64 | \seealso{ 65 | \code{\link{as.list.rdeque}} for conversion to a list and the generic \code{\link{as.data.frame}}. 66 | } 67 | 68 | -------------------------------------------------------------------------------- /man/as.data.frame.rstack.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/as.data.frame.rstack.R 3 | \name{as.data.frame.rstack} 4 | \alias{as.data.frame.rstack} 5 | \title{Convert an rstack to a data.frame} 6 | \usage{ 7 | \method{as.data.frame}{rstack}(x, row.names = NULL, optional = FALSE, ...) 8 | } 9 | \arguments{ 10 | \item{x}{rstack to convert.} 11 | 12 | \item{row.names}{passed on to \code{as.data.frame} before final conversion.} 13 | 14 | \item{optional}{passed onto \code{as.data.frame} before final conversion.} 15 | 16 | \item{...}{passed onto \code{as.data.frame} before final conversion.} 17 | } 18 | \value{ 19 | a data.frame with the first row the previous top of the stack. 20 | } 21 | \description{ 22 | Converts the elements of an rstack into rows of a data.frame, if this is reasonable. 23 | } 24 | \details{ 25 | This function runs in \eqn{O(N)} time in the size of the rstack, and will only work if all 26 | elements of the stack have the same length() (e.g., same number of columns), and if any of the 27 | elements have names, then those names do not conflict (e.g., same column names where used). 28 | This is accomplished by a call to 29 | \code{do.call("rbind", as.list.rstack(x))}, where \code{\link{as.list.rstack}} converts the rstack to a list 30 | where the top element becomes the first element of the list. 31 | } 32 | \examples{ 33 | s <- rstack() 34 | s <- insert_top(s, data.frame(names = c("Bob", "Joe"), ages = c(25, 18))) 35 | s <- insert_top(s, data.frame(names = c("Mary", "Kate", "Ashley"), ages = c(27, 26, 21))) 36 | print(s) 37 | 38 | sd <- as.data.frame(s) 39 | print(sd) 40 | 41 | ## Elements may be similarly-named lists as well, representing individual rows: 42 | s <- rstack() 43 | s <- insert_top(s, list(name = "Bob", age = 25)) 44 | s <- insert_top(s, list(name = "Mary", age = 24)) 45 | print(s) 46 | 47 | sd <- as.data.frame(s) 48 | print(sd) 49 | 50 | ## Building a stack in a loop, converting to a dataframe after the fact: 51 | s <- rstack() 52 | for(i in 1:1000) { 53 | if(runif(1,0,1) < 0.5) { 54 | s <- insert_top(s, data.frame(i = i, type = "sqrt", val = sqrt(i))) 55 | } else { 56 | s <- insert_top(s, data.frame(i = i, type = "log", val = log(i))) 57 | } 58 | if(i \%\% 100 == 0) { 59 | print(i/1000) 60 | } 61 | } 62 | print(head(as.data.frame(s))) 63 | } 64 | \seealso{ 65 | \code{\link{as.list.rstack}} for conversion to a list and the generic \code{\link{as.data.frame}}. 66 | } 67 | 68 | -------------------------------------------------------------------------------- /man/as.list.rdeque.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/as.list.rdeque.R 3 | \name{as.list.rdeque} 4 | \alias{as.list.rdeque} 5 | \title{Convert an rdeque to a list} 6 | \usage{ 7 | \method{as.list}{rdeque}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{rdeque to convert.} 11 | 12 | \item{...}{additional arguments passed to as.list after initial conversion to list.} 13 | } 14 | \value{ 15 | a list containing the elements of the rdeqeue in front-to-back order. 16 | } 17 | \description{ 18 | Converts an rdeque to a list, where the front of the deque becomes 19 | the first element of the list, the second-from-front the second, and so on. 20 | } 21 | \details{ 22 | Runs in \eqn{O(N)} time in the size of the rdeque, but the generated list is pre-allocated for efficiency. 23 | } 24 | \examples{ 25 | d <- rdeque() 26 | d <- insert_front(d, "a") 27 | d <- insert_front(d, "b") 28 | 29 | dlist <- as.list(d) 30 | print(dlist) 31 | } 32 | \seealso{ 33 | \code{\link{as.data.frame.rstack}} and the generic \code{\link{as.list}}. 34 | } 35 | 36 | -------------------------------------------------------------------------------- /man/as.list.rstack.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/as.list.rstack.R 3 | \name{as.list.rstack} 4 | \alias{as.list.rstack} 5 | \title{Convert an rstack to a list} 6 | \usage{ 7 | \method{as.list}{rstack}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{rstack to convert.} 11 | 12 | \item{...}{additional arguments passed to as.list after initial conversion to list.} 13 | } 14 | \value{ 15 | a list containing the elements of the stack in top-to-bottom order. 16 | } 17 | \description{ 18 | Converts an rstack to a list, where the top of the stack becomes 19 | the first element of the list, the second-from-top the second, and so on. 20 | } 21 | \details{ 22 | Runs in \eqn{O(N)} time in the size of the stack, but the generated list is pre-allocated for efficiency. 23 | } 24 | \examples{ 25 | s <- rstack() 26 | s <- insert_top(s, "a") 27 | s <- insert_top(s, "b") 28 | 29 | slist <- as.list(s) 30 | print(slist) 31 | } 32 | \seealso{ 33 | \code{\link{as.data.frame.rstack}} 34 | } 35 | 36 | -------------------------------------------------------------------------------- /man/as.rdeque.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/as.rdeque.R 3 | \name{as.rdeque} 4 | \alias{as.rdeque} 5 | \title{Create a pre-filled rdeque from a given input} 6 | \usage{ 7 | as.rdeque(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{input to convert to an rdeque.} 11 | 12 | \item{...}{additional arguments to be passed to or from methods (ignored).} 13 | } 14 | \value{ 15 | a new rdeque. 16 | } 17 | \description{ 18 | Creates a new rdeque from a given input. Coerces input to a 19 | list first using \code{as.list}, the element at \code{x[[1]]} becomes the front of the new rdeque. 20 | } 21 | \details{ 22 | Runs in \eqn{O(N)} in the size of the input. Because data.frames return a list of 23 | columns when run through \code{as.list}, running \code{as.rdeque} results in a deque of 24 | columns, rather than a deque of rows. 25 | } 26 | \examples{ 27 | d <- as.rdeque(1:20) 28 | print(d) 29 | 30 | d <- as.rdeque(1:200000) 31 | print(d) 32 | 33 | ## A deck with only 5 elements, one for each column 34 | oops <- as.rdeque(iris) 35 | print(oops) 36 | } 37 | \seealso{ 38 | \code{\link{rdeque}}. 39 | } 40 | 41 | -------------------------------------------------------------------------------- /man/as.rstack.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/as.rstack.R 3 | \name{as.rstack} 4 | \alias{as.rstack} 5 | \title{Create an rstack pre-filled from a given input} 6 | \usage{ 7 | as.rstack(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{input to convert to a stack.} 11 | 12 | \item{...}{additional arguments to be passed to or from methods.} 13 | } 14 | \value{ 15 | a new rstack. 16 | } 17 | \description{ 18 | Creates a new rstack from a given input. Coerces input to a 19 | list first using \code{as.list}, the element at \code{x[[1]]} becomes the top of the new rstack. 20 | } 21 | \details{ 22 | Runs in \eqn{O(N)} in the size of the input. Because data frames return a list of 23 | columns when run through \code{as.list}, running \code{as.rstack} results in a stack of 24 | columns, rather than a stack of rows. 25 | } 26 | \examples{ 27 | s <- as.rstack(1:20) 28 | print(s) 29 | 30 | s <- as.rstack(1:200000) 31 | print(s) 32 | 33 | ## A stack with only 5 elements, one for each column 34 | oops <- as.rstack(iris) 35 | print(oops) 36 | } 37 | \seealso{ 38 | \code{\link{rstack}}. 39 | } 40 | 41 | -------------------------------------------------------------------------------- /man/head.rstack.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/head.rstack.R 3 | \name{head.rstack} 4 | \alias{head.rstack} 5 | \title{Return the head (top) of an rstack} 6 | \usage{ 7 | \method{head}{rstack}(x, n = 6L, ...) 8 | } 9 | \arguments{ 10 | \item{x}{rstack to get the head/top of.} 11 | 12 | \item{n}{number of elements to get.} 13 | 14 | \item{...}{arguments to be passed to or from other methods (ignored).} 15 | } 16 | \value{ 17 | an \code{\link{rstack}}. 18 | } 19 | \description{ 20 | Returns the top \eqn{n} elements of an rstack as an stack, or all of the elements 21 | if \code{length(x) < n}. 22 | } 23 | \details{ 24 | Runs in \eqn{O(n)} time (in the size of the number of elements requested). 25 | } 26 | \examples{ 27 | s <- rstack() 28 | s <- insert_top(s, "a") 29 | s <- insert_top(s, "b") 30 | s <- insert_top(s, "c") 31 | 32 | st <- head(s, n = 2) 33 | print(st) 34 | print(s) 35 | } 36 | \seealso{ 37 | \code{\link{rstack}}. 38 | } 39 | 40 | -------------------------------------------------------------------------------- /man/insert_back.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/insert_back.R 3 | \name{insert_back} 4 | \alias{insert_back} 5 | \title{Insert an element into the back of an rdeque or rpqueue} 6 | \usage{ 7 | insert_back(x, e, ...) 8 | } 9 | \arguments{ 10 | \item{x}{rdeque or rpqueue to insert onto.} 11 | 12 | \item{e}{element to insert.} 13 | 14 | \item{...}{additional arguments to be passed to or from methods (ignored).} 15 | } 16 | \value{ 17 | modified version of the rdeque or rpqueue. 18 | } 19 | \description{ 20 | Returns a version of the deque/queue with the new element in the back position. 21 | } 22 | \details{ 23 | Runs in \eqn{O(1)} time worst-case. Does not modify the original. 24 | } 25 | \examples{ 26 | d <- rdeque() 27 | d <- insert_back(d, "a") 28 | d <- insert_back(d, "b") 29 | print(d) 30 | 31 | d2 <- insert_back(d, "c") 32 | print(d2) 33 | print(d) 34 | } 35 | \references{ 36 | Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 37 | } 38 | 39 | -------------------------------------------------------------------------------- /man/insert_front.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/insert_front.R 3 | \name{insert_front} 4 | \alias{insert_front} 5 | \title{Insert an element into the front of an rdeque} 6 | \usage{ 7 | insert_front(d, e, ...) 8 | } 9 | \arguments{ 10 | \item{d}{rdeque to insert onto.} 11 | 12 | \item{e}{element to insert.} 13 | 14 | \item{...}{additional arguments to be passed to or from methods (ignored).} 15 | } 16 | \value{ 17 | modified version of the rdeque. 18 | } 19 | \description{ 20 | Returns a version of the deque with the new element in the front position. 21 | } 22 | \details{ 23 | Runs in \eqn{O(1)} time worst-case. Does not modify the original rdeque. 24 | } 25 | \examples{ 26 | d <- rdeque() 27 | d <- insert_front(d, "a") 28 | d <- insert_front(d, "b") 29 | print(d) 30 | 31 | d2 <- insert_front(d, "c") 32 | print(d2) 33 | print(d) 34 | } 35 | \references{ 36 | Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 37 | } 38 | \seealso{ 39 | \code{\link{without_front}} for removing the front element. 40 | } 41 | 42 | -------------------------------------------------------------------------------- /man/insert_top.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/insert_top.R 3 | \name{insert_top} 4 | \alias{insert_top} 5 | \title{Insert an element onto the top of an rstack} 6 | \usage{ 7 | insert_top(s, e, ...) 8 | } 9 | \arguments{ 10 | \item{s}{rstack to insert onto.} 11 | 12 | \item{e}{element to insert.} 13 | 14 | \item{...}{additional arguments to be passed to or from methods (ignored).} 15 | } 16 | \value{ 17 | modified version of the stack with new element at top. 18 | } 19 | \description{ 20 | Insert an element onto the top of an rstack. 21 | } 22 | \details{ 23 | Runs in \eqn{O(1)} time worst-case. Does not semantically modify the original structure (i.e, this 24 | function is "pure"). 25 | } 26 | \examples{ 27 | s <- rstack() 28 | s <- insert_top(s, "a") 29 | s <- insert_top(s, "b") 30 | print(s) 31 | 32 | s2 <- insert_top(s, "c") 33 | print(s2) 34 | print(s) 35 | } 36 | \references{ 37 | Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 38 | } 39 | \seealso{ 40 | \code{\link{rstack}} for information on rstacks, \code{\link{without_top}} for removal of top elements. 41 | } 42 | 43 | -------------------------------------------------------------------------------- /man/length.rdeque.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/length.rdeque.R 3 | \name{length.rdeque} 4 | \alias{length.rdeque} 5 | \title{Return the number of elements in an rdeque} 6 | \usage{ 7 | \method{length}{rdeque}(x) 8 | } 9 | \arguments{ 10 | \item{x}{rdeque to get the length of.} 11 | } 12 | \value{ 13 | a vector of length 1 with the number of elements. 14 | } 15 | \description{ 16 | Returns the number of elements in an rdeque. 17 | } 18 | \details{ 19 | Runs in \eqn{O(1)} time, as this information is stored seperately and updated on every insert/remove. 20 | } 21 | \examples{ 22 | d <- rdeque() 23 | d <- insert_front(d, "a") 24 | print(length(d)) # 1 25 | d <- insert_back(d, "b") 26 | print(length(d)) # 2 27 | } 28 | \seealso{ 29 | \code{\link{empty}} for checking whether an rdeque is empty. 30 | } 31 | 32 | -------------------------------------------------------------------------------- /man/length.rstack.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/length.rstack.R 3 | \name{length.rstack} 4 | \alias{length.rstack} 5 | \title{Return the number of elements in an rstack} 6 | \usage{ 7 | \method{length}{rstack}(x) 8 | } 9 | \arguments{ 10 | \item{x}{rstack to get the length of.} 11 | } 12 | \value{ 13 | a vector of length 1, which the number of elements of the stack. 14 | } 15 | \description{ 16 | Returns the number of elements in an rstack. 17 | } 18 | \details{ 19 | Runs in \eqn{O(1)} time, as this information is stored seperately and updated on every insert/remove. 20 | } 21 | \examples{ 22 | s <- rstack() 23 | s <- insert_top(s, "a") 24 | print(length(s)) # 1 25 | s <- insert_top(s, "b") 26 | print(length(s)) # 2 27 | } 28 | \seealso{ 29 | \code{\link{empty}} for checking whether an rstack is empty. 30 | } 31 | 32 | -------------------------------------------------------------------------------- /man/peek_back.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/peek_back.R 3 | \name{peek_back} 4 | \alias{peek_back} 5 | \title{Return the data element at the back of an rdeque} 6 | \usage{ 7 | peek_back(d, ...) 8 | } 9 | \arguments{ 10 | \item{d}{rdeque to peek at.} 11 | 12 | \item{...}{additional arguments to be passed to or from methods (ignored).} 13 | } 14 | \value{ 15 | data element existing at the back of the rdeque. 16 | } 17 | \description{ 18 | Simply returns the data element sitting at the back of the rdeque, 19 | leaving the rdeque alone. 20 | } 21 | \details{ 22 | Runs in \code{O(1)} worst-case time. 23 | } 24 | \examples{ 25 | d <- rdeque() 26 | d <- insert_front(d, "a") 27 | d <- insert_front(d, "b") 28 | e <- peek_back(d) 29 | print(e) 30 | print(d) 31 | 32 | ## Assigning to the front data element with peek_front: 33 | d <- rdeque() 34 | d <- insert_front(d, data.frame(a = 1, b = 1)) 35 | d <- insert_front(d, data.frame(a = 1, b = 1)) 36 | 37 | peek_back(d)$a <- 100 38 | print(d) 39 | 40 | peek_back(d) <- data.frame(a = 100, b = 100) 41 | print(d) 42 | } 43 | \seealso{ 44 | \code{\link{without_back}} for removing the front element. 45 | } 46 | 47 | -------------------------------------------------------------------------------- /man/peek_front.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/peek_front.R 3 | \name{peek_front} 4 | \alias{peek_front} 5 | \title{Return the data element at the front of an rdeque} 6 | \usage{ 7 | peek_front(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{rdeque to look at.} 11 | 12 | \item{...}{additional arguments to be passed to or from methods (ignored).} 13 | } 14 | \value{ 15 | data element at the front of the rdeque. 16 | } 17 | \description{ 18 | Simply returns the data element sitting at the front of the deque, 19 | leaving the deque alone. 20 | } 21 | \details{ 22 | Runs in \eqn{O(1)} worst-case time. 23 | } 24 | \examples{ 25 | d <- rdeque() 26 | d <- insert_front(d, "a") 27 | d <- insert_back(d, "b") 28 | e <- peek_front(d) 29 | print(e) 30 | print(d) 31 | } 32 | 33 | -------------------------------------------------------------------------------- /man/peek_top.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/peek_top.R 3 | \name{peek_top} 4 | \alias{peek_top} 5 | \title{Return the data element at the top of an rstack} 6 | \usage{ 7 | peek_top(s, ...) 8 | } 9 | \arguments{ 10 | \item{s}{rstack to peek at.} 11 | 12 | \item{...}{additional arguments to be passed to or from methods (ignored).} 13 | } 14 | \value{ 15 | data element existing at the top of the rstack. 16 | } 17 | \description{ 18 | Simply returns the data element sitting at the top of the rstack, 19 | leaving the rstack alone. 20 | } 21 | \details{ 22 | Runs in \code{O(1)} worst-case time. 23 | } 24 | \examples{ 25 | s <- rstack() 26 | s <- insert_top(s, "a") 27 | s <- insert_top(s, "b") 28 | e <- peek_top(s) 29 | print(e) 30 | print(s) 31 | 32 | ## Assigning to the top data element with peek_top: 33 | s <- rstack() 34 | s <- insert_top(s, data.frame(a = 1, b = 1)) 35 | s <- insert_top(s, data.frame(a = 1, b = 1)) 36 | 37 | peek_top(s)$a <- 100 38 | print(s) 39 | 40 | peek_top(s) <- data.frame(a = 100, b = 100) 41 | } 42 | \seealso{ 43 | \code{\link{without_top}} for removing the top element. 44 | } 45 | 46 | -------------------------------------------------------------------------------- /man/rdeque.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/rdeque.R 3 | \name{rdeque} 4 | \alias{rdeque} 5 | \title{Create a new empty rdeque} 6 | \usage{ 7 | rdeque() 8 | } 9 | \value{ 10 | a new empty rdeque. 11 | } 12 | \description{ 13 | Creates a new, empty, rdeque ready for use. 14 | } 15 | \details{ 16 | An rdeque provided both "Last In, First Out" (LIFO) and "First In, First Out" (FIFO) access; 17 | envisaged as queue, elements may be added or removed from the front or the back with \code{\link{insert_front}}, 18 | \code{\link{insert_back}}, \code{\link{without_front}}, and \code{\link{without_back}}. The front and back 19 | elements may be retrieved with \code{\link{peek_front}} and \code{\link{peek_back}}. 20 | 21 | Internally, rdeques are stored as a pair of rstacks; they provide \eqn{O(1)}-amortized insertion and removal, 22 | so long as they are not used persistently (that is, the variable storing the deque is always replaced 23 | by the modified version, e.g. \code{s <- without_front(s)}). When used persistently (e.g. \code{s2 <- without_front(s)}, which results 24 | in two deques being accessible), this cannot be gauranteed. When an \eqn{O(1)} worst-cast, fully 25 | persistent FIFO queue is needed, the rpqueue from this package provides these semantics. However, 26 | there is a constant-time overhead for rpqueues, such that rdeques are often more efficient (and flexible) 27 | in practice, even in when used persistently. 28 | 29 | Other useful functions 30 | include \code{as.list} and \code{as.data.frame} (the latter of which requires that 31 | all elements can be appended to become rows of a data frame in a reasonable manner). 32 | } 33 | \examples{ 34 | d <- rdeque() 35 | d <- insert_front(d, "a") 36 | d <- insert_front(d, "b") 37 | d <- insert_back(d, "c") 38 | d <- insert_back(d, "d") 39 | print(d) 40 | 41 | d2 <- without_back(d) 42 | print(d2) 43 | print(d) 44 | 45 | b <- peek_front(d) 46 | print(b) 47 | } 48 | \references{ 49 | Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 50 | } 51 | \seealso{ 52 | \code{\link{rstack}} for a fast LIFO-only structure. 53 | } 54 | 55 | -------------------------------------------------------------------------------- /man/rev.rstack.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/rev.rstack.R 3 | \name{rev.rstack} 4 | \alias{rev.rstack} 5 | \title{Reverse an rstack} 6 | \usage{ 7 | \method{rev}{rstack}(x) 8 | } 9 | \arguments{ 10 | \item{x}{rstack to reverse.} 11 | } 12 | \value{ 13 | a reversed version of the rstack. 14 | } 15 | \description{ 16 | Returns a reversed version of an rstack, where the old last element (generally 17 | inaccessible) is now the top (and thus now accessible). 18 | } 19 | \details{ 20 | This method runs in \eqn{O(N)} in the size of the rstack, though it works behind-the-scenes 21 | for efficiency by converting the input stack 22 | to a list, reversing the list, and building the result as a new rstack. The original is thus 23 | left alone, preserving \eqn{O(1)} amortized time for the original (assuming the "cost" of reversing 24 | is charged to the newly created stack) at the cost of additional memory usage. But, 25 | if the stack is not being used in a preserved manner, e.g. \code{s <- rev(s)}, the garbage collector 26 | will be free to clean up the original data if it is no longer usable. 27 | } 28 | \examples{ 29 | s <- rstack() 30 | s <- insert_top(s, "a") 31 | s <- insert_top(s, "b") 32 | s <- insert_top(s, "c") 33 | 34 | r <- rev(s) 35 | print(r) 36 | print(s) 37 | } 38 | \seealso{ 39 | \code{\link{as.list.rstack}} for converting an rstack to a list. 40 | } 41 | 42 | -------------------------------------------------------------------------------- /man/rstack.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/rstack.R 3 | \name{rstack} 4 | \alias{rstack} 5 | \title{Create a new, empty rstack} 6 | \usage{ 7 | rstack() 8 | } 9 | \value{ 10 | an empty rstack. 11 | } 12 | \description{ 13 | An rstack is a "Last In, First Out" (LIFO) structure imagined as being organized from 14 | top (last in) to bottom (first in), supporting efficient insertion into the 15 | top, removal from the top, and peeking/accessing the top element. All functions supported by rstacks are 16 | side-effect free. 17 | } 18 | \details{ 19 | Other handy functions supported by rstacks 20 | include \code{as.list} and \code{as.data.frame} (the latter of which requires that 21 | all elements can be appended to become rows of a data frame in a reasonable manner). Operations 22 | are amortized \eqn{O(1)}. 23 | 24 | The rstack class also supports \code{\link{rev}} - this operation is \eqn{O(N)}, and results in a copy. This 25 | means previous versions will retain their \eqn{O(1)} amortized nature (if we assume the cost of the 26 | reverse is charged to the newly created stack), at the cost of memory usage. However, this also means 27 | that if stacks are used in a non-persistent way, e.g. \code{s <- rev(s)}, then the garbage collector 28 | is free to clean up old versions of the data. 29 | } 30 | \examples{ 31 | s <- rstack() 32 | s <- insert_top(s, "a") 33 | s <- insert_top(s, "b") 34 | print(s) 35 | 36 | sl <- without_top(s) 37 | print(sl) 38 | print(s) 39 | 40 | b <- peek_top(s) 41 | print(b) 42 | } 43 | \references{ 44 | Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 45 | } 46 | \seealso{ 47 | \code{\link{insert_top}} for insertion, \code{\link{without_top}} for removal, 48 | and \code{\link{peek_top}} for peeking. 49 | } 50 | 51 | -------------------------------------------------------------------------------- /man/rstacknode.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/rstacknode.R 3 | \name{rstacknode} 4 | \alias{rstacknode} 5 | \title{Internal structure used by rstacks, rdeques, and rpqueues} 6 | \usage{ 7 | rstacknode(data) 8 | } 9 | \arguments{ 10 | \item{data}{data to reference with this node.} 11 | } 12 | \value{ 13 | an environment. 14 | } 15 | \description{ 16 | For use by rstacks and rdeques. Simply an environment with no parent, 17 | reference for the data and the next node. 18 | } 19 | 20 | -------------------------------------------------------------------------------- /man/without_back.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/without_back.R 3 | \name{without_back} 4 | \alias{without_back} 5 | \title{Return a version of an rdeque without the back element} 6 | \usage{ 7 | without_back(d, ...) 8 | } 9 | \arguments{ 10 | \item{d}{rdeque to remove elements from.} 11 | 12 | \item{...}{additional arguments to be passed to or from methods (ignored).} 13 | } 14 | \value{ 15 | version of the rdeque with the back element removed. 16 | } 17 | \description{ 18 | Simply returns a version of the given rdeque without the back element 19 | The original rdeque is left alone. 20 | } 21 | \details{ 22 | Runs in \eqn{O(1)}-amortized time if the rdeque is used non-persistently (see documentation 23 | of \code{\link{rdeque}} for details). If the given rdeque is empty, an error will be generated. 24 | } 25 | \examples{ 26 | d <- rdeque() 27 | d <- insert_front(d, "a") 28 | d <- insert_front(d, "b") 29 | d <- insert_front(d, "c") 30 | 31 | d2 <- without_back(d) 32 | print(d2) 33 | 34 | d3 <- without_back(d) 35 | print(d3) 36 | 37 | print(d) 38 | } 39 | \references{ 40 | Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 41 | } 42 | \seealso{ 43 | \code{\link{insert_back}} for inserting elements. 44 | } 45 | 46 | -------------------------------------------------------------------------------- /man/without_front.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/without_front.R 3 | \name{without_front} 4 | \alias{without_front} 5 | \title{Return a version of an rdeque or rpqueue without the front element} 6 | \usage{ 7 | without_front(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{rdeque or rpqueue to remove elements from.} 11 | 12 | \item{...}{additional arguments to be passed to or from methods (ignored).} 13 | } 14 | \value{ 15 | a version of the rdeque or rpqueue with the front element removed. 16 | } 17 | \description{ 18 | Return a version of an rdeque or rpqueue without the front element 19 | } 20 | \details{ 21 | Simply returns a version of the given structure without the front element. 22 | The original is left alone. 23 | } 24 | \examples{ 25 | d <- rdeque() 26 | d <- insert_front(d, "a") 27 | d <- insert_front(d, "b") 28 | d <- insert_back(d, "c") 29 | 30 | d2 <- without_front(d) 31 | print(d2) 32 | 33 | d3 <- without_front(d2) 34 | print(d3) 35 | 36 | print(d) 37 | } 38 | \references{ 39 | Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 40 | } 41 | 42 | -------------------------------------------------------------------------------- /man/without_top.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2 (4.1.1): do not edit by hand 2 | % Please edit documentation in R/without_top.R 3 | \name{without_top} 4 | \alias{without_top} 5 | \title{Return a version of an rstack without the top element} 6 | \usage{ 7 | without_top(s, ...) 8 | } 9 | \arguments{ 10 | \item{s}{rstack to remove elements from.} 11 | 12 | \item{...}{additional arguments to be passed to or from methods (ignored).} 13 | } 14 | \value{ 15 | version of the stack with the top \eqn{n} elements removed. 16 | } 17 | \description{ 18 | Simply returns a version of the given stack without the top element. Results in an error if the structure is empty. 19 | The original rstack is left alone. 20 | } 21 | \details{ 22 | Runs in \eqn{O(1)} time worst case. 23 | } 24 | \examples{ 25 | s <- rstack() 26 | s <- insert_top(s, "a") 27 | s <- insert_top(s, "b") 28 | s <- insert_top(s, "c") 29 | 30 | s2 <- without_top(s) 31 | print(s2) 32 | 33 | print(s) 34 | } 35 | \references{ 36 | Okasaki, Chris. Purely Functional Data Structures. Cambridge University Press, 1999. 37 | } 38 | \seealso{ 39 | \code{\link{insert_top}} for inserting elements. 40 | } 41 | 42 | -------------------------------------------------------------------------------- /rstackdeque.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(rstackdeque) 3 | 4 | test_check("rstackdeque") 5 | -------------------------------------------------------------------------------- /tests/testthat/test.rdeque.R: -------------------------------------------------------------------------------- 1 | test_that("peek_front assignment works as expected", { 2 | d <- rdeque() 3 | d <- insert_front(d, data.frame(a = 1, b = 2)) 4 | d <- insert_front(d, data.frame(a = 3, b = 4)) 5 | peek_front(d)$a <- 300 6 | 7 | dlist <- as.list(d) 8 | expect_that(dlist[[1]], equals(data.frame(a = 300, b = 4))) 9 | 10 | peek_front(d) <- data.frame(a = 300, b = 400) 11 | dlist <- as.list(d) 12 | expect_that(dlist[[1]], equals(data.frame(a = 300, b = 400))) 13 | }) 14 | 15 | test_that("peek_back assignment works as expected", { 16 | d <- rdeque() 17 | d <- insert_front(d, data.frame(a = 1, b = 2)) 18 | d <- insert_front(d, data.frame(a = 3, b = 4)) 19 | peek_back(d)$a <- 100 20 | 21 | dlist <- as.list(d) 22 | expect_that(dlist[[2]], equals(data.frame(a = 100, b = 2))) 23 | 24 | peek_back(d) <- data.frame(a = 100, b = 2) 25 | dlist <- as.list(d) 26 | expect_that(dlist[[2]], equals(data.frame(a = 100, b = 2))) 27 | }) 28 | 29 | 30 | test_that("insert_front and without_front work as expected", { 31 | s <- rdeque() 32 | s <- insert_front(s, "c") 33 | s <- insert_front(s, "b") 34 | s <- insert_front(s, "a") 35 | expect_that(length(s), equals(3)) 36 | expect_that(as.list(s), is_identical_to(as.list(c("a", "b", "c"))) ) 37 | 38 | ## drop one 39 | sp <- without_front(s) 40 | expect_that(length(sp), equals(2)) 41 | expect_that(as.list(sp), is_identical_to(as.list(c("b", "c"))) ) 42 | 43 | ## s still ok? 44 | expect_that(length(s), equals(3)) 45 | expect_that(as.list(s), is_identical_to(as.list(c("a", "b", "c"))) ) 46 | 47 | ## add one 48 | se <- insert_front(s, "aa") 49 | expect_that(length(se), equals(4)) 50 | expect_that(as.list(se), is_identical_to(as.list(c("aa", "a", "b", "c"))) ) 51 | 52 | ## s still ok? 53 | expect_that(length(s), equals(3)) 54 | expect_that(as.list(s), is_identical_to(as.list(c("a", "b", "c"))) ) 55 | 56 | s <- without_front(s) 57 | s <- without_front(s) 58 | s <- without_front(s) 59 | expect_that(empty(s), equals(TRUE)) 60 | }) 61 | 62 | 63 | test_that("peek_front and peek_back work for nearly-empty deques", { 64 | d <- rdeque() 65 | d <- insert_front(d, "a") 66 | expect_that(peek_front(d), equals("a")) 67 | expect_that(peek_back(d), equals("a")) 68 | 69 | d2 <- rdeque() 70 | d2 <- insert_front(d2, "a") 71 | expect_that(peek_front(d2), equals("a")) 72 | expect_that(peek_back(d2), equals("a")) 73 | 74 | d3 <- rdeque() 75 | d3 <- insert_front(d3, "a") 76 | d3 <- insert_front(d3, "b") 77 | expect_that(peek_front(d3), equals("b")) 78 | expect_that(peek_back(d3), equals("a")) 79 | 80 | d4 <- rdeque() 81 | d4 <- insert_back(d4, "a") 82 | d4 <- insert_back(d4, "b") 83 | expect_that(peek_back(d4), equals("b")) 84 | expect_that(peek_front(d4), equals("a")) 85 | }) 86 | 87 | test_that("insert_back and without_back work as expected", { 88 | s <- rdeque() 89 | s <- insert_back(s, "c") 90 | s <- insert_back(s, "b") 91 | s <- insert_back(s, "a") 92 | expect_that(length(s), equals(3)) 93 | expect_that(as.list(s), is_identical_to(as.list(c("c", "b", "a"))) ) 94 | 95 | ## drop one 96 | sp <- without_back(s) 97 | expect_that(length(sp), equals(2)) 98 | expect_that(as.list(sp), is_identical_to(as.list(c("c", "b"))) ) 99 | 100 | ## s still ok? 101 | expect_that(length(s), equals(3)) 102 | expect_that(as.list(s), is_identical_to(as.list(c("c", "b", "a"))) ) 103 | 104 | ## add one 105 | se <- insert_back(s, "aa") 106 | expect_that(length(se), equals(4)) 107 | expect_that(as.list(se), is_identical_to(as.list(c("c", "b", "a", "aa"))) ) 108 | 109 | ## s still ok? 110 | expect_that(length(s), equals(3)) 111 | expect_that(as.list(s), is_identical_to(as.list(c("c", "b", "a"))) ) 112 | 113 | s <- without_back(s) 114 | s <- without_back(s) 115 | s <- without_back(s) 116 | expect_that(empty(s), equals(TRUE)) 117 | 118 | }) 119 | -------------------------------------------------------------------------------- /tests/testthat/test.rpqueue.R: -------------------------------------------------------------------------------- 1 | test_that("peek_front assignment works as expected", { 2 | d <- rpqueue() 3 | d <- insert_back(d, data.frame(a = 1, b = 2)) 4 | d <- insert_back(d, data.frame(a = 3, b = 4)) 5 | peek_front(d)$a <- 100 6 | 7 | dlist <- as.list(d) 8 | expect_that(dlist[[1]], equals(data.frame(a = 100, b = 2))) 9 | 10 | peek_front(d) <- data.frame(a = 100, b = 200) 11 | dlist <- as.list(d) 12 | expect_that(dlist[[1]], equals(data.frame(a = 100, b = 200))) 13 | }) 14 | 15 | 16 | test_that("insert_back and without_front work as expected", { 17 | s <- rpqueue() 18 | s <- insert_back(s, "c") 19 | s <- insert_back(s, "b") 20 | s <- insert_back(s, "a") 21 | expect_that(length(s), equals(3)) 22 | expect_that(as.list(s), is_identical_to(as.list(c("c", "b", "a"))) ) 23 | 24 | ## drop one 25 | sp <- without_front(s) 26 | expect_that(length(sp), equals(2)) 27 | expect_that(as.list(sp), is_identical_to(as.list(c("b", "a"))) ) 28 | 29 | ## s still ok? 30 | expect_that(length(s), equals(3)) 31 | expect_that(as.list(s), is_identical_to(as.list(c("c", "b", "a"))) ) 32 | 33 | ## add one 34 | se <- insert_back(s, "aa") 35 | expect_that(length(se), equals(4)) 36 | expect_that(as.list(se), is_identical_to(as.list(c("c", "b", "a", "aa"))) ) 37 | 38 | ## s still ok? 39 | expect_that(length(s), equals(3)) 40 | expect_that(as.list(s), is_identical_to(as.list(c("c", "b", "a"))) ) 41 | 42 | s <- without_front(s) 43 | s <- without_front(s) 44 | s <- without_front(s) 45 | expect_that(empty(s), equals(TRUE)) 46 | 47 | }) 48 | 49 | -------------------------------------------------------------------------------- /tests/testthat/test.stack.R: -------------------------------------------------------------------------------- 1 | test_that("peek_top assignment works as expected", { 2 | s <- rstack() 3 | s <- insert_top(s, data.frame(a = 1, b = 2)) 4 | s <- insert_top(s, data.frame(a = 3, b = 4)) 5 | peek_top(s)$a <- 300 6 | 7 | slist <- as.list(s) 8 | expect_that(slist[[1]], equals(data.frame(a = 300, b = 4))) 9 | 10 | peek_top(s) <- data.frame(a = 300, b = 400) 11 | slist <- as.list(s) 12 | expect_that(slist[[1]], equals(data.frame(a = 300, b = 400))) 13 | }) 14 | 15 | 16 | test_that("insert and remove work as expected", { 17 | s <- rstack() 18 | s <- insert_top(s, "c") 19 | s <- insert_top(s, "b") 20 | s <- insert_top(s, "a") 21 | expect_that(length(s), equals(3)) 22 | expect_that(as.list(s), is_identical_to(as.list(c("a", "b", "c"))) ) 23 | 24 | ## drop one 25 | sp <- without_top(s) 26 | expect_that(length(sp), equals(2)) 27 | expect_that(as.list(sp), is_identical_to(as.list(c("b", "c"))) ) 28 | 29 | ## s still ok? 30 | expect_that(length(s), equals(3)) 31 | expect_that(as.list(s), is_identical_to(as.list(c("a", "b", "c"))) ) 32 | 33 | ## add one 34 | se <- insert_top(s, "aa") 35 | expect_that(length(se), equals(4)) 36 | expect_that(as.list(se), is_identical_to(as.list(c("aa", "a", "b", "c"))) ) 37 | 38 | ## s still ok? 39 | expect_that(length(s), equals(3)) 40 | expect_that(as.list(s), is_identical_to(as.list(c("a", "b", "c"))) ) 41 | }) --------------------------------------------------------------------------------