4 Random Access Lists
Following Random Access List structures implement and provide the functions list, empty?, cons, head, tail, list-ref, list-set, drop, list-length and ->list. The implementations of the two data structures are based on numerical representations. Binary random access lists uses the binary number representation and running time of its basic list and random access operations, in worst-case, is logarithmic. Where as skew binary random access lists use skew binary number representation and running time of its basic operations is constant in worst-case. And both the implementations are polymorphic. And our benchmarks indicate that the operations of skew binary random access lists are faster.
4.1 Binary Random Access List
(require (planet krhari/pfds:1:5/binaryrandomaccesslist)) |
Random Access Lists are list data structures that provide array-like lookup and update operations. They have been implemented as a framework of binary numerical representation using complete binary leaf trees. It has a worst case running time of O(log(n)) for the operations cons, first, rest, list-ref and list-set.
(List A) |
Example: |
> (list 1 2 3 4 5 6) |
- : (U Null (Root Positive-Fixnum)) |
#<Root> |
In the above example, (list 1 2 3 4 5 6) gives a Binary Random Access List which is similar to lists but comes with efficient list-ref and list-set operations.
In the above example, (cons 10 (list 5 3 5 6)) returns (list 10 5 3 5 6).
Examples: |
> (rest (list 1 2 3 4 5 6)) |
- : (U Null (Root Positive-Fixnum)) |
#<Root> |
> (rest empty) |
tail: given list is empty |
In the above example, (rest ral) returns the rest of the given list, (list 2 3 4 5 6).
Examples: |
> (list-ref (list 12 5 3 2 15 23) 4) |
- : Positive-Fixnum |
15 |
> (list-ref (list 12 5 3 2 15 23) 10) |
list-ref: given index out of bound |
Examples: |
> (list-set (list 1 2 3 4 5 6) 2 10) |
- : (U Null (Root Positive-Fixnum)) |
#<Root> |
> (list-set (list 1 2 3 4 5 6) 10 15) |
list-set: given index out of bound |
In the above example, (list-set (list 1 2 3 4 5 6) 2 10) returns (list 1 2 10 4 5 6) and (list-set (list 1 2 3 4 5 6) 10 15) throws an error.
Examples: |
> (define ral (list 1 2 3 4 5 6)) |
> (->list ral) |
- : (Listof Positive-Fixnum) |
'(1 2 3 4 5 6) |
In the above example, (->list ral) returns (list 1 2 3 4 5 6).
Examples: |
> (drop 3 (list 1 2 3 4 5 6)) |
- : (U Null (Root Positive-Fixnum)) |
#<Root> |
> (drop 10 (list 1 2 3 4 5 6)) |
drop: not enough elements to drop |
In the above example, (drop 3 (list 1 2 3 4 5 6)) returns the list (list 4 5 6). (drop 10 (list 1 2 3 4 5 6)) throws an error since 10 is larger than the number of elements in the list.
Examples: |
> (length (list 1 2 3 4 5 6)) |
- : Integer |
6 |
> (length empty) |
- : Integer |
0 |
Example: |
> (->list (reverse (list 1 2 3 4 5 6))) |
- : (Listof Positive-Fixnum) |
'(6 5 4 3 2 1) |
Examples: |
> (->list (map add1 (list 1 2 3 4 5 6))) |
- : (Listof Exact-Positive-Integer) |
'(2 3 4 5 6 7) |
> (->list (map * (list 1 2 3 4 5 6) (list 1 2 3 4 5 6))) |
- : (Listof Exact-Positive-Integer) |
'(1 4 9 16 25 36) |
In the above example, (map add1 (list 1 2 3 4 5 6)) adds 1 to each element of the given list and returns (list 2 3 4 5 6 7). (map * (list 1 2 3 4 5 6) (list 1 2 3 4 5 6)) multiplies corresponding elements in the two lists and returns the list (list 1 4 9 16 25 36).
(foldl func init lst1 lst2 ...) → C |
func : (C A B ... B -> C) |
init : C |
lst1 : (List A) |
lst2 : (List B) |
foldl currently does not produce correct results when the given function is non-commutative.
Examples: |
> (foldl + 0 (list 1 2 3 4 5 6)) |
- : Exact-Nonnegative-Integer |
21 |
> (foldl * 1 (list 1 2 3 4 5 6) (list 1 2 3 4 5 6)) |
- : Exact-Positive-Integer |
518400 |
(foldr func init lst1 lst2 ...) → C |
func : (C A B ... B -> C) |
init : C |
lst1 : (List A) |
lst2 : (List B) |
foldr currently does not produce correct results when the given function is non-commutative.
Examples: |
> (foldr + 0 (list 1 2 3 4 5 6)) |
- : Exact-Nonnegative-Integer |
21 |
> (foldr * 1 (list 1 2 3 4 5 6) (list 1 2 3 4 5 6)) |
- : Exact-Positive-Integer |
518400 |
Examples: |
> (andmap even? (list 1 2 3 4 5 6)) |
- : Boolean |
#f |
> (andmap odd? (list 1 2 3 4 5 6)) |
- : Boolean |
#f |
> (andmap positive? (list 1 2 3 4 5 6)) |
- : Boolean |
#t |
> (andmap negative? (list -1 -2)) |
- : Boolean |
#t |
Examples: |
> (ormap even? (list 1 2 3 4 5 6)) |
- : Boolean |
#t |
> (ormap odd? (list 1 2 3 4 5 6)) |
- : Boolean |
#t |
> (ormap positive? (list -1 -2 3 4 -5 6)) |
- : Boolean |
#t |
> (ormap negative? (list 1 -2)) |
- : Boolean |
#t |
(build-list size func) → (List A) |
size : Natural |
func : (Natural -> A) |
Examples: |
> (->list (build-list 5 (λ:([x : Integer]) (add1 x)))) |
- : (Listof Integer) |
'(1 2 3 4 5) |
> (->list (build-list 5 (λ:([x : Integer]) (* x x)))) |
- : (Listof Integer) |
'(0 1 4 9 16) |
Examples: |
> (->list (make-list 5 10)) |
- : (Listof Positive-Fixnum) |
'(10 10 10 10 10) |
> (->list (make-list 5 'sym)) |
- : (Listof 'sym) |
'(sym sym sym sym sym) |
Examples: |
> (define lst (list 1 2 3 4 5 6)) |
> (->list (filter (λ:([x : Integer]) (> x 5)) lst)) |
- : (Listof Positive-Fixnum) |
'(6) |
> (->list (filter (λ:([x : Integer]) (< x 5)) lst)) |
- : (Listof Positive-Fixnum) |
'(1 2 3 4) |
> (->list (filter (λ:([x : Integer]) (<= x 4)) lst)) |
- : (Listof Positive-Fixnum) |
'(1 2 3 4) |
Examples: |
> (->list (remove (λ:([x : Integer]) (> x 5)) (list 1 2 3 4 5 6))) |
- : (Listof Positive-Fixnum) |
'(1 2 3 4 5) |
> (->list (remove (λ:([x : Integer]) (< x 5)) (list 1 2 3 4 5 6))) |
- : (Listof Positive-Fixnum) |
'(5 6) |
> (->list (remove (λ:([x : Integer]) (<= x 4)) (list 1 2 3 4 5 6))) |
- : (Listof Positive-Fixnum) |
'(5 6) |
Example: |
> (second (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
2 |
Example: |
> (third (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
3 |
Example: |
> (fourth (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
4 |
Example: |
> (fifth (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
5 |
Example: |
> (sixth (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
6 |
Example: |
> (seventh (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
7 |
Example: |
> (eighth (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
8 |
Example: |
> (ninth (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
9 |
Example: |
> (tenth (list 1 2 3 4 5 6 7 8 9 10 11)) |
- : Positive-Fixnum |
10 |
Examples: |
> (last (list 1 2 3 4 5 6 7 8 9 10 11)) |
- : Positive-Fixnum |
11 |
> (last (list 1 2 3 4 5)) |
- : Positive-Fixnum |
5 |
4.2 Skew Binary Random Access List
(require (planet krhari/pfds:1:5/skewbinaryrandomaccesslist)) |
Random Access Lists are list data structures that provide array-like lookup and update operations. Skew Binary Random Access Lists are implemented using skew binary numbers. It provides a worst case running time of O(1) for the operations cons, first and rest and O(log(n)) for the operations list-ref and list-set.
(List A) |
Example: |
> (list 1 2 3 4 5 6) |
- : (Listof (Pairof Integer (U (Leaf Positive-Fixnum) (Node Positive-Fixnum)))) |
(list (cons 3 (Node 1 (Leaf 2) (Leaf 3))) (cons 3 (Node 4 (Leaf 5) (Leaf 6)))) |
In the above example, (list 1 2 3 4 5 6) gives a Skew Binary Random Access List which is similar to lists and has efficient lookup and update operations.
Example: |
> (cons 10 (list 1 2 3 4 5 6)) |
- : (Listof (Pairof Integer (U (Leaf Positive-Fixnum) (Node Positive-Fixnum)))) |
(list (cons 7 (Node 10 (Node 1 (Leaf 2) (Leaf 3)) (Node 4 (Leaf 5) (Leaf 6))))) |
In the above example, (cons 10 (list 1 2 3 4 5 6)) returns a (list 10 1 2 3 4 5 6).
Examples: |
> (first (list 1 2 3 4 5 6)) |
- : Positive-Fixnum |
1 |
> (first empty) |
head: given list is empty |
Examples: |
> (rest (list 1 2 3 4 5 6)) |
- : (Listof (Pairof Integer (U (Leaf Positive-Fixnum) (Node Positive-Fixnum)))) |
(list (cons 1 (Leaf 2)) (cons 1 (Leaf 3)) (cons 3 (Node 4 (Leaf 5) (Leaf 6)))) |
> (rest empty) |
tail: given list is empty |
In the above example, (rest (list 1 2 3 4 5 6)) returns the (list 2 3 4 5 6).
Examples: |
> (list-ref (list 1 2 3 4 5 6) 0) |
- : Positive-Fixnum |
1 |
> (list-ref (list 1 2 3 4 5 6) 3) |
- : Positive-Fixnum |
4 |
> (list-ref (list 1 2 3 4 5 6) 10) |
list-ref: given index out of bounds |
Examples: |
> (->list (list-set (list 1 2 3 4 5 6) 3 10)) |
- : (Listof Positive-Fixnum) |
'(1 2 3 10 5 6) |
> (->list (list-set (list 1 2 3 4 5 6) 6 10)) |
list-set: given index out of bounds |
In the above example, (list-set (list 1 2 3 4 5 6) 3 10) returns (list 1 2 3 10 5 6), (list-set (list 1 2 3 4 5 6) 6 10) throws an error since there are only six elements in the list and it is trying to update seventh element.
Examples: |
> (->list (list 1 2 3 4 5 6)) |
- : (Listof Positive-Fixnum) |
'(1 2 3 4 5 6) |
> (->list empty) |
- : (Listof Nothing) |
'() |
Examples: |
> (drop 3 (list 1 2 3 4 5 6)) |
- : (Listof (Pairof Integer (U (Leaf Positive-Fixnum) (Node Positive-Fixnum)))) |
(list (cons 3 (Node 4 (Leaf 5) (Leaf 6)))) |
> (drop 0 (list 1 2 3 4 5 6)) |
- : (Listof (Pairof Integer (U (Leaf Positive-Fixnum) (Node Positive-Fixnum)))) |
(list (cons 3 (Node 1 (Leaf 2) (Leaf 3))) (cons 3 (Node 4 (Leaf 5) (Leaf 6)))) |
> (drop 10 (list 1 2 3 4 5 6)) |
drop: not enough elements to drop |
In the above example, (drop 3 (list 1 2 3 4 5 6) 3) returns (list 4 5 6). (drop 0 (list 1 2 3 4 5 6)) returns the (list 1 2 3 4 5 6). If the given n is larger than the number of elements in the list, then it throws an error.
Examples: |
> (length (list 1 2 3 4 5 6)) |
- : Integer |
6 |
> (length (list 1 2 3)) |
- : Integer |
3 |
> (length empty) |
- : Integer |
0 |
Example: |
> (->list (reverse (list 1 2 3 4 5 6))) |
- : (Listof Positive-Fixnum) |
'(6 5 4 3 2 1) |
map currently works on only upto 3 lists because of some issues with contracts.
Examples: |
> (->list (map add1 (list 1 2 3 4 5 6))) |
- : (Listof Exact-Positive-Integer) |
'(2 3 4 5 6 7) |
> (->list (map * (list 1 2 3 4 5 6) (list 1 2 3 4 5 6))) |
- : (Listof Exact-Positive-Integer) |
'(1 4 9 16 25 36) |
In the above example, (map add1 (list 1 2 3 4 5 6)) adds 1 to each element of the given list and returns (list 2 3 4 5 6 7). (map * (list 1 2 3 4 5 6) (list 1 2 3 4 5 6)) multiplies corresponding elements in the two lists and returns the list (list 1 4 9 16 25 36).
(foldl func init lst1 lst2 ...) → C |
func : (C A B ... B -> C) |
init : C |
lst1 : (List A) |
lst2 : (List B) |
foldl currently does not produce correct results when the given function is non-commutative.
Examples: |
> (foldl + 0 (list 1 2 3 4 5 6)) |
- : Exact-Nonnegative-Integer |
21 |
> (foldl * 1 (list 1 2 3 4 5 6) (list 1 2 3 4 5 6)) |
- : Exact-Positive-Integer |
518400 |
(foldr func init lst1 lst2 ...) → C |
func : (C A B ... B -> C) |
init : C |
lst1 : (List A) |
lst2 : (List B) |
foldr currently does not produce correct results when the given function is non-commutative.
Examples: |
> (foldr + 0 (list 1 2 3 4 5 6)) |
- : Exact-Nonnegative-Integer |
21 |
> (foldr * 1 (list 1 2 3 4 5 6) (list 1 2 3 4 5 6)) |
- : Exact-Positive-Integer |
518400 |
Examples: |
> (andmap even? (list 1 2 3 4 5 6)) |
- : Boolean |
#f |
> (andmap odd? (list 1 2 3 4 5 6)) |
- : Boolean |
#f |
> (andmap positive? (list 1 2 3 4 5 6)) |
- : Boolean |
#t |
> (andmap negative? (list -1 -2)) |
- : Boolean |
#t |
Examples: |
> (ormap even? (list 1 2 3 4 5 6)) |
- : Boolean |
#t |
> (ormap odd? (list 1 2 3 4 5 6)) |
- : Boolean |
#t |
> (ormap positive? (list -1 -2 3 4 -5 6)) |
- : Boolean |
#t |
> (ormap negative? (list 1 -2)) |
- : Boolean |
#t |
(build-list size func) → (List A) |
size : Natural |
func : (Natural -> A) |
Examples: |
> (->list (build-list 5 (λ:([x : Integer]) (add1 x)))) |
- : (Listof Integer) |
'(1 2 3 4 5) |
> (->list (build-list 5 (λ:([x : Integer]) (* x x)))) |
- : (Listof Integer) |
'(0 1 4 9 16) |
Examples: |
> (->list (make-list 5 10)) |
- : (Listof Positive-Fixnum) |
'(10 10 10 10 10) |
> (->list (make-list 5 'sym)) |
- : (Listof 'sym) |
'(sym sym sym sym sym) |
Examples: |
> (define lst (list 1 2 3 4 5 6)) |
> (->list (filter (λ:([x : Integer]) (> x 5)) lst)) |
- : (Listof Positive-Fixnum) |
'(6) |
> (->list (filter (λ:([x : Integer]) (< x 5)) lst)) |
- : (Listof Positive-Fixnum) |
'(1 2 3 4) |
> (->list (filter (λ:([x : Integer]) (<= x 4)) lst)) |
- : (Listof Positive-Fixnum) |
'(1 2 3 4) |
Examples: |
> (->list (remove (λ:([x : Integer]) (> x 5)) (list 1 2 3 4 5 6))) |
- : (Listof Positive-Fixnum) |
'(1 2 3 4 5) |
> (->list (remove (λ:([x : Integer]) (< x 5)) (list 1 2 3 4 5 6))) |
- : (Listof Positive-Fixnum) |
'(5 6) |
> (->list (remove (λ:([x : Integer]) (<= x 4)) (list 1 2 3 4 5 6))) |
- : (Listof Positive-Fixnum) |
'(5 6) |
Example: |
> (second (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
2 |
Example: |
> (third (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
3 |
Example: |
> (fourth (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
4 |
Example: |
> (fifth (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
5 |
Example: |
> (sixth (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
6 |
Example: |
> (seventh (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
7 |
Example: |
> (eighth (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
8 |
Example: |
> (ninth (list 1 2 3 4 5 6 7 8 9 10)) |
- : Positive-Fixnum |
9 |
Example: |
> (tenth (list 1 2 3 4 5 6 7 8 9 10 11)) |
- : Positive-Fixnum |
10 |
Examples: |
> (last (list 1 2 3 4 5 6 7 8 9 10 11)) |
- : Positive-Fixnum |
11 |
> (last (list 1 2 3 4 5)) |
- : Positive-Fixnum |
5 |