├── .gitattributes ├── .gitignore ├── .travis.yml ├── README.md ├── info.rkt └── pfds ├── catenable-list.rkt ├── delay.rkt ├── deque ├── bankers.rkt ├── implicit.rkt └── real-time.rkt ├── heap ├── binomial.rkt ├── bootstrapped.rkt ├── lazy-pairing.rkt ├── leftist.rkt ├── pairing.rkt ├── skew-binomial.rkt └── splay.rkt ├── info.rkt ├── partialstream.rkt ├── queue ├── bankers.rkt ├── bootstrapped.rkt ├── hood-melville.rkt ├── implicit.rkt ├── physicists.rkt └── real-time.rkt ├── ralist ├── binary.rkt └── skew.rkt ├── red-black-tree.rkt ├── scribblings ├── bankers-deque.scrbl ├── binaryrandomaccesslist.scrbl ├── binomialheap.scrbl ├── bootstrapedheap.scrbl ├── bootstrapedqueue.scrbl ├── catenable-list.scrbl ├── deques.scrbl ├── functional-data-structures.scrbl ├── heaps.scrbl ├── helper.rkt ├── hood-melville-queue.scrbl ├── implicitdeque.scrbl ├── implicitqueue.scrbl ├── lazypairingheap.scrbl ├── leftistheap.scrbl ├── pairingheap.scrbl ├── physicists-queue.scrbl ├── queue.scrbl ├── queues.scrbl ├── randomaccesslist.scrbl ├── realtimedeque.scrbl ├── realtimequeue.scrbl ├── redblacktrees.scrbl ├── skewbinaryrandomaccesslist.scrbl ├── skewbinomialheap.scrbl ├── splayheap.scrbl ├── streams.scrbl ├── treap.scrbl ├── tries.scrbl └── vlist.scrbl ├── stream.rkt ├── tests ├── bankers-deque-benchmarks.rkt ├── bankers-deque-tests.rkt ├── bankers-queue-benchmarks.rkt ├── bankers-queue-tests.rkt ├── binary-ran-access-list-tests.rkt ├── binomialheap-tests.rkt ├── bootstrapedheap-tests.rkt ├── bootstrapedqueue-tests.rkt ├── catenablelist-tests.rkt ├── hood-melville-queue-tests.rkt ├── implicitdeque-performance-tests.rkt ├── implicitdeque-tests.rkt ├── implicitqueue-performance-tests.rkt ├── implicitqueue-tests.rkt ├── lazypairingheap-test.rkt ├── leftistheaps-tests.rkt ├── pairingheap-test.rkt ├── partialstream-tests.rkt ├── physicists-queue-tests.rkt ├── realtimedeque-tests.rkt ├── realtimequeue-tests.rkt ├── redblacktrees-tests.rkt ├── skewbinaryrandomaccesslist-tests.rkt ├── skewbinomialheap-tests.rkt ├── splayheap-tests.rkt ├── stream-tests.rkt ├── tests-main.rkt ├── treap-tests.rkt ├── tries-test.rkt └── vlist-tests.rkt ├── treap.rkt ├── trie.rkt └── vlist.rkt /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=author 2 | 3 | *.rkt text 4 | *.scrbl text 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.un~ 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: c 4 | 5 | env: 6 | - PATH=~/racket/bin:$PATH 7 | 8 | before_install: 9 | - "export DISPLAY=:99.0" 10 | - "sh -e /etc/init.d/xvfb start" 11 | - curl -L -o installer.sh http://plt.eecs.northwestern.edu/snapshots/current/installers/racket-test-current-x86_64-linux-precise.sh 12 | - sh installer.sh --in-place --dest ~/racket/ 13 | 14 | install: 15 | - curl -L -o master.zip https://github.com/takikawa/tr-pfds/archive/master.zip 16 | - unzip master.zip 17 | - raco pkg install -n pfds pfds/ 18 | 19 | script: 20 | - raco test -c pfds/tests 21 | - echo "done" 22 | 23 | after_script: 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Functional Data Structures for Typed Racket 2 | =========================================== 3 | 4 | [![Build Status](https://travis-ci.org/takikawa/tr-pfds.svg?branch=master)](https://travis-ci.org/takikawa/tr-pfds) 5 | [![Scribble](https://img.shields.io/badge/Docs-Scribble-blue.svg)](https://docs.racket-lang.org/functional-data-structures/index.html) 6 | 7 | This library provides several functional data structures based on the work 8 | of Chris Okasaki and Phil Bagwell. Click the badge above the documentation. 9 | 10 | The original library was implemented by Hari Prashanth. 11 | 12 | How to install 13 | -------------- 14 | 15 | Use one of: 16 | 17 | * `raco pkg install pfds` 18 | 19 | or 20 | 21 | * `git clone git://github.com/takikawa/tr-pfds.git` 22 | * `raco pkg install tr-pfds/` 23 | 24 | On Racket v5.3.1 or older, use `raco` to link this repository as 25 | a Racket collection. Here are step-by-step instructions: 26 | 27 | * `git clone git://github.com/takikawa/tr-pfds.git` 28 | * `cd tr-pfds/pfds` 29 | * `raco link .` 30 | * `raco setup pfds` 31 | 32 | This will link the `pfds` folder as a collection called `pfds`. 33 | Then you can require, for example, the Bankers Deque by using 34 | `(require pfds/deque/bankers)`. 35 | 36 | Data structures 37 | --------------- 38 | 39 | The following data structures are implemented: 40 | 41 | * Deques 42 | + Bankers Deque `pfds/deque/bankers` 43 | + Implicit Deque `pfds/deque/implicit` 44 | + Real-Time Deque `pfds/deque/real-time` 45 | * Heaps 46 | + Binomial Heap `pfds/heap/binomial` 47 | + Skew Binomial Heap `pfds/heap/skew-binomial` 48 | + Leftist Heap `pfds/heap/leftist` 49 | + Splay Heap `pfds/heap/splay` 50 | + Pairing Heap `pfds/heap/pairing` 51 | + Lazy Pairing Heap `pfds/heap/lazy-pairing` 52 | + Bootstrapped Heap `pfds/heap/bootstrapped` 53 | * Queues 54 | + Bankers Queue `pfds/queue/bankers` 55 | + Physicist's Queue `pfds/queue/physicists` 56 | + Hood-Melville Queue `pfds/queue/hood-melville` 57 | + Implicit Queue `pfds/queue/implicit` 58 | + Real-Time Queue `pfds/queue/real-time` 59 | * Random Access Lists 60 | + Binary Random Access List `pfds/ralist/binary` 61 | + Skew Binary Random Access List `pfds/ralist/skew` 62 | * Catenable List `pfds/catenable-list` 63 | * VList `pfds/vlist` 64 | * Streams `pfds/stream` 65 | * Red-Black Trees `pfds/red-black-tree` 66 | * Tries `pfds/trie` 67 | * Treap `pfds/treap` 68 | -------------------------------------------------------------------------------- /info.rkt: -------------------------------------------------------------------------------- 1 | #lang setup/infotab 2 | 3 | ;; Planet 2 4 | (define collection 'multi) 5 | (define deps '("base" "typed-racket-lib" "typed-racket-compatibility" "scheme-lib")) 6 | (define build-deps '("at-exp-lib" "htdp-lib" "racket-doc" "scribble-lib" "typed-racket-more")) 7 | 8 | (define version "0.1") 9 | -------------------------------------------------------------------------------- /pfds/delay.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | ;; basic delay and force implementations for typed/racket based on lambda + box 4 | ;; used in okasaki data structure implementations 5 | (provide Promiseof delay force) 6 | 7 | ;; - Outer box is for memoization 8 | ;; - Inner box is so TR can distinguished a forced promise from an unforced one 9 | ;; I would have used a struct like Prom instead of the inner box, but TR 10 | ;; cannnot distinguish structs from procedures? 11 | (define-type (Promiseof A) 12 | (Boxof (U (-> (Boxof A)) (Boxof A)))) 13 | 14 | 15 | (define-syntax-rule (delay e) (box (λ () (box e)))) 16 | 17 | (: force : (All (A) ((Promiseof A) -> A))) 18 | (define (force b) 19 | (let ([ub (unbox b)]) 20 | (if (procedure? ub) 21 | (let ([v (ub)]) 22 | (set-box! b v) 23 | (unbox v)) 24 | (unbox ub)))) 25 | -------------------------------------------------------------------------------- /pfds/info.rkt: -------------------------------------------------------------------------------- 1 | #lang setup/infotab 2 | 3 | (define name "Library of Functional Data Structures in Typed Racket") 4 | (define blurb 5 | '("A library of purely functional data structures in Typed Racket. 6 | Data structures in the library are based on Chris Okasaki's book, 7 | Purely Functional Data Structures and 8 | work by Phil Bagwell and others")) 9 | (define primary-file (list "queue/bankers.rkt" 10 | "queue/bootstrapped.rkt" 11 | "queue/hood-melville.rkt" 12 | "queue/implicit.rkt" 13 | "queue/physicists.rkt" 14 | "queue/real-time.rkt" 15 | "deque/bankers.rkt" 16 | "deque/implicit.rkt" 17 | "deque/real-time.rkt" 18 | "ralist/binary.rkt" 19 | "ralist/skew.rkt" 20 | "heap/binomial.rkt" 21 | "heap/bootstrapped.rkt" 22 | "heap/lazy-pairing.rkt" 23 | "heap/leftist.rkt" 24 | "heap/pairing.rkt" 25 | "heap/skew-binomial.rkt" 26 | "heap/splay.rkt" 27 | "catenable-list.rkt" 28 | "red-black-trees.rkt" 29 | "vlist.rkt" 30 | "stream/streams.rkt" 31 | "set.rkt" 32 | "trie.rkt" 33 | "treap.rkt")) 34 | (define categories '(datastructures)) 35 | (define can-be-loaded-with 'all) 36 | (define release-notes 37 | (list '(ul (li "Updated to Racket 5.3.1")))) 38 | (define version "2.0") 39 | (define scribblings '(("scribblings/functional-data-structures.scrbl" (multi-page) ("Data Structures")))) 40 | -------------------------------------------------------------------------------- /pfds/partialstream.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | ;; A "partial stream" is a list where the tail of each of the segments may or 4 | ;; may not be delayed. Thus, both a completely eager list and a standard stream 5 | ;; (where all tails are delayed) are instances of a partial stream. 6 | 7 | ;; A partial stream is practically advantageous over a standard stream in cases 8 | ;; where delaying the tail has no benefit. An example is when the tail is null. 9 | ;; Since null is already a value, delaying it has no advantages. Another example 10 | ;; is when the tail is the result of reversing a stream. Since reverse is a 11 | ;; monolithic operation, ie it traverses the entire list or stream regardless 12 | ;; of laziness, any suspensions in the result have no benefit (but still incur 13 | ;; the cost of creating them). A situation where the latter example occurs is in 14 | ;; banker's queue. 15 | 16 | (require "delay.rkt") 17 | 18 | (provide PartialStreamof pscar pscdr psappend pstake psdrop psreverse) 19 | 20 | (define-type (PartialStreamof A) 21 | (Rec X (U Null 22 | (Pair A X) 23 | (Promiseof X)))) 24 | 25 | (: pscar : (All (A) ((PartialStreamof A) -> A))) 26 | (define (pscar lst) 27 | (cond [(null? lst) (error 'pscar "given list is empty")] 28 | [(pair? lst) (car lst)] 29 | [else (pscar (force lst))])) 30 | 31 | (: pscdr : (All (A) ((PartialStreamof A) -> (PartialStreamof A)))) 32 | (define (pscdr lst) 33 | (cond [(null? lst) (error 'pscdr "given list is empty")] 34 | [(pair? lst) (cdr lst)] 35 | [else (pscdr (force lst))])) 36 | 37 | (: psappend : 38 | (All (A) (PartialStreamof A) (PartialStreamof A) -> (PartialStreamof A))) 39 | (define (psappend l1 l2) 40 | (cond [(null? l1) l2] 41 | [(null? l2) l1] 42 | [(pair? l1) (cons (car l1) (ann (delay (psappend (cdr l1) l2)) 43 | (PartialStreamof A)))] 44 | [else (psappend (force l1) l2)])) 45 | 46 | (: pstake : (All (A) (Integer (PartialStreamof A) -> (PartialStreamof A)))) 47 | (define (pstake num lst) 48 | (cond [(zero? num) null] 49 | [(null? lst) (error 'pstake "not enough elements to take")] 50 | [(pair? lst) (cons (car lst) (ann (delay (pstake (sub1 num) (cdr lst))) 51 | (PartialStreamof A)))] 52 | [else (pstake num (force lst))])) 53 | 54 | (: psdrop : (All (A) (Integer (PartialStreamof A) -> (PartialStreamof A)))) 55 | (define (psdrop num lst) 56 | (cond [(zero? num) lst] 57 | [(null? lst) (error 'psdrop "not enough elements to drop")] 58 | [(pair? lst) (psdrop (sub1 num) (cdr lst))] 59 | [else (psdrop num (force lst))])) 60 | 61 | (: psreverse : (All (A) (PartialStreamof A) -> (PartialStreamof A))) 62 | (define (psreverse lst) 63 | (: loop : (All (A) (PartialStreamof A) (PartialStreamof A) -> (PartialStreamof A))) 64 | (define (loop lst accum) 65 | (cond [(null? lst) accum] 66 | [(pair? lst) (loop (cdr lst) (cons (car lst) accum))] 67 | [else (loop (force lst) accum)])) 68 | (loop lst null)) 69 | -------------------------------------------------------------------------------- /pfds/scribblings/binomialheap.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/heap/binomial)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/heap/binomial)) 9 | 10 | @title{Binomial Heap} 11 | 12 | @defmodule[pfds/heap/binomial] 13 | 14 | Binomial Heaps are nothing but mergeable priority heaps. To avoid the 15 | confusion with FIFO queues, they are referred as heaps. Heaps are similar 16 | to the sortable collections but the difference is that comparison function 17 | is fixed when the heap is created. Binomial heaps are a binary representation 18 | with heap-ordered, binomial trees. A tree is heap-ordered if it maintains 19 | min-heap or max-heap property. 20 | Provides worst case running time of @bold{@italic{O(log(n))}} for the 21 | operations @scheme[insert], @scheme[find-min/max], @scheme[delete-min/max] 22 | and @scheme[merge]. 23 | 24 | @defform[(Heap A)]{A binomial heap of type @racket[A].} 25 | 26 | @defproc[(heap [comp (A A -> Boolean)] [a A] ...) (Heap A)]{ 27 | Function @scheme[heap] creates a Binomial Heap with the given 28 | inputs. 29 | @examples[#:eval evaluate 30 | (heap < 1 2 3 4 5 6) 31 | ] 32 | 33 | In the above example, the binomial heap obtained will have elements 1 thru' 6 34 | with < as the comparison function. 35 | } 36 | 37 | @;defform/none[empty]{ 38 | @;An empty binomial heap.} 39 | 40 | @defproc[(empty? [heap (Heap A)]) Boolean]{ 41 | Function @scheme[empty?] checks if the given binomial heap is empty or not. 42 | 43 | @examples[#:eval evaluate 44 | 45 | (empty? (heap < 1 2 3 4 5 6)) 46 | (empty? (heap <)) 47 | 48 | ]} 49 | 50 | @defproc[(insert [a A] [heap (Heap A)] ...) (Heap A)]{ 51 | Function @scheme[insert] takes an element and a binomial heap and inserts 52 | the given element into the binomial heap. 53 | @examples[#:eval evaluate 54 | 55 | (insert 10 (heap < 1 2 3)) 56 | 57 | ] 58 | 59 | In the above example, @scheme[insert] adds the element 10 to 60 | @scheme[(heap < 1 2 3)].} 61 | 62 | @defproc[(find-min/max [heap (Heap A)]) A]{ 63 | Function @scheme[find-min/max] takes a binomial heap and gives the 64 | largest or the smallest element in the heap if binomial heap is not empty 65 | else throws an error. The element returned is largest or smallest depends 66 | on the comparison function of the heap. 67 | @examples[#:eval evaluate 68 | 69 | (find-min/max (heap < 1 2 3 4 5 6)) 70 | 71 | (find-min/max (heap > 1 2 3 4 5 6)) 72 | 73 | (find-min/max (heap <)) 74 | ]} 75 | 76 | @defproc[(delete-min/max [heap (Heap A)]) (Heap A)]{ 77 | Function @scheme[delete-min/max] takes a binomial heap and returns the 78 | same heap without the min or max element in the given heap. The element 79 | removed from the heap is max or min depends on the comparison function of the 80 | heap. 81 | @examples[#:eval evaluate 82 | 83 | (delete-min/max (heap < 1 2 3 4 5 6)) 84 | (delete-min/max (heap > 1 2 3 4 5 6)) 85 | (delete-min/max (heap <)) 86 | ] 87 | 88 | In the above example, @scheme[(delete-min/max (heap < 1 2 3 4 5 6))], 89 | deletes the element 1(min) from the heap. And 90 | @scheme[(delete-min/max (heap > 1 2 3 4 5 6))], deletes 91 | the element 6(max) from the heap.} 92 | 93 | @defproc[(merge [bheap1 (Heap A)] [bheap2 (Heap A)]) (Heap A)]{ 94 | Function @scheme[merge] takes two binomial heaps and returns a 95 | merged binomial heap. Uses the comparison function of the first heap for 96 | merging and the same function becomes the comparison function for the 97 | merged heap. 98 | 99 | @margin-note{If the comparison 100 | functions do not have the same properties, merged heap might lose its 101 | heap-order.} 102 | @examples[#:eval evaluate 103 | 104 | (define bheap1 (heap < 1 2 3 4 5 6)) 105 | (define bheap2 (heap (λ: ([a : Integer] 106 | [b : Integer]) 107 | (< a b)) 108 | 10 20 30 40 50 60)) 109 | (merge bheap1 bheap2) 110 | 111 | ] 112 | 113 | In the above example, @scheme[(merge bheap1 bheap2)], merges the heaps and 114 | < will become the comparison function for the merged heap.} 115 | 116 | 117 | @defproc[(sorted-list [heap (Heap A)]) (Listof A)]{ 118 | Function @scheme[sorted-list] takes a binomial heap and returns a list 119 | which is sorted according to the comparison function of the heap. 120 | @examples[#:eval evaluate 121 | 122 | (sorted-list (heap > 1 2 3 4 5 6)) 123 | (sorted-list (heap < 1 2 3 4 5 6)) 124 | ]} 125 | 126 | @defproc[(map [comparer (C C -> Boolean)] 127 | [func (A B ... B -> C)] 128 | [hep1 (Heap A)] 129 | [hep2 (Heap B)] ...) (Heap A)]{ 130 | Function @scheme[map] is similar to @|racket-map| for lists. 131 | @examples[#:eval evaluate 132 | 133 | (sorted-list (map < add1 (heap < 1 2 3 4 5 6))) 134 | 135 | (sorted-list (map < * (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6))) 136 | ]} 137 | 138 | @defproc[(fold [func (C A B ... B -> C)] 139 | [init C] 140 | [hep1 (Heap A)] 141 | [hep2 (Heap B)] ...) C]{ 142 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 143 | @margin-note{@scheme[fold] currently does not produce correct results when the 144 | given function is non-commutative.} 145 | 146 | @examples[#:eval evaluate 147 | 148 | (fold + 0 (heap < 1 2 3 4 5 6)) 149 | 150 | (fold * 1 (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6)) 151 | ]} 152 | 153 | @defproc[(filter [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 154 | Function @scheme[filter] is similar to @|racket-filter|. 155 | @examples[#:eval evaluate 156 | 157 | (define hep (heap < 1 2 3 4 5 6)) 158 | 159 | (sorted-list (filter (λ: ([x : Integer]) (> x 5)) hep)) 160 | 161 | (sorted-list (filter (λ: ([x : Integer]) (< x 5)) hep)) 162 | 163 | (sorted-list (filter (λ: ([x : Integer]) (<= x 5)) hep)) 164 | ]} 165 | 166 | @defproc[(remove [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 167 | Function @scheme[remove] is similar to @|racket-filter| but 168 | @scheme[remove] removes the elements which match the predicate. 169 | @examples[#:eval evaluate 170 | 171 | (sorted-list (remove (λ: ([x : Integer]) (> x 5)) 172 | (heap < 1 2 3 4 5 6))) 173 | 174 | (sorted-list (remove (λ: ([x : Integer]) (< x 5)) 175 | (heap < 1 2 3 4 5 6))) 176 | 177 | (sorted-list (remove (λ: ([x : Integer]) (<= x 5)) 178 | (heap < 1 2 3 4 5 6))) 179 | ]} 180 | 181 | @defproc[(andmap [func (A B ... B -> Boolean)] 182 | [heap1 (Heap A)] 183 | [heap2 (Heap B)] ...) Boolean]{ 184 | Function @scheme[andmap] is similar to @|racket-andmap|. 185 | 186 | @examples[#:eval evaluate 187 | 188 | (andmap even? (heap < 1 2 3 4 5 6)) 189 | 190 | (andmap odd? (heap < 1 2 3 4 5 6)) 191 | 192 | (andmap positive? (heap < 1 2 3 4 5 6)) 193 | 194 | (andmap negative? (heap < -1 -2)) 195 | ]} 196 | 197 | 198 | @defproc[(ormap [func (A B ... B -> Boolean)] 199 | [heap1 (Heap A)] 200 | [heap2 (Heap B)] ...) Boolean]{ 201 | Function @scheme[ormap] is similar to @|racket-ormap|. 202 | 203 | @examples[#:eval evaluate 204 | 205 | (ormap even? (heap < 1 2 3 4 5 6)) 206 | 207 | (ormap odd? (heap < 1 2 3 4 5 6)) 208 | 209 | (ormap positive? (heap < -1 -2 3 4 -5 6)) 210 | 211 | (ormap negative? (heap < 1 -2)) 212 | ]} 213 | 214 | @defproc[(build-heap [size Natural] 215 | [func (Natural -> A)] 216 | [comp (A A -> Boolean)]) 217 | (Heap A)]{ 218 | Function @scheme[build-heap] is similar to @|racket-build-list| but this 219 | function takes an extra comparison function. 220 | 221 | @examples[#:eval evaluate 222 | 223 | (sorted-list (build-heap 5 (λ:([x : Integer]) (add1 x)) <)) 224 | 225 | (sorted-list (build-heap 5 (λ:([x : Integer]) (* x x)) <)) 226 | 227 | ]} 228 | 229 | @(close-eval evaluate) 230 | -------------------------------------------------------------------------------- /pfds/scribblings/bootstrapedheap.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/heap/bootstrapped)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/heap/bootstrapped)) 9 | 10 | @title{Bootstrapped Heap} 11 | 12 | @defmodule[pfds/heap/bootstrapped] 13 | 14 | Bootstrapped heaps are heaps with efficient merging. The bootstrapped heap is 15 | implemented with structural abstraction over a less efficient heap 16 | implementation to get a worst case running time of @bold{@italic{O(1)}} for the 17 | operations @scheme[insert], @scheme[find-min/max] and @scheme[merge] and worst 18 | case running time of @bold{@italic{O(log(n))}} for @scheme[delete-min/max] 19 | operation. This implementation abstracts over skew binomial heaps. For skew 20 | binomial heaps, see @secref["skewbh"]. 21 | 22 | @defform[(Heap A)]{A bootstrapped heap of type @racket[A].} 23 | 24 | @defproc[(heap [comp (A A -> Boolean)] [a A] ...) (Heap A)]{ 25 | Function @scheme[heap] creates a Bootstrapped Heap with the 26 | given inputs. 27 | @examples[#:eval evaluate 28 | 29 | (heap < 1 2 3 4 5 6) 30 | ] 31 | 32 | In the above example, the bootstrapped heap obtained will have elements 33 | 1 thru' 6 with < as the comparison function.} 34 | 35 | 36 | @defproc[(empty? [heap (Heap A)]) Boolean]{ 37 | Function @scheme[empty?] checks if the given bootstrapped heap is empty 38 | or not. 39 | @examples[#:eval evaluate 40 | 41 | (empty? (heap < 1 2 3 4 5 6)) 42 | 43 | (empty? (heap <)) 44 | 45 | ]} 46 | 47 | 48 | @defproc[(insert [a A] [heap (Heap A)] ...) (Heap A)]{ 49 | Function @scheme[insert] takes an element and a bootstrapped heap and inserts 50 | the given element into the bootstrapped heap. 51 | @examples[#:eval evaluate 52 | 53 | (insert 10 (heap < 1 2 3 4 5 6)) 54 | ] 55 | 56 | In the above example, insert adds the element 10 to the heap 57 | @scheme[(heap < 1 2 3 4 5 6)].} 58 | 59 | @defproc[(find-min/max [heap (Heap A)]) A]{ 60 | Function @scheme[find-min/max] takes a bootstrapped heap and gives the 61 | largest or the smallest element in the heap if bootstrapped heap is not empty 62 | else throws an error. The element returned is largest or smallest depends on 63 | the comparison function of the heap. 64 | @examples[#:eval evaluate 65 | 66 | (find-min/max (heap < 1 2 3 4 5 6)) 67 | (find-min/max (heap > 1 2 3 4 5 6)) 68 | (find-min/max (heap <)) 69 | ]} 70 | 71 | @defproc[(delete-min/max [heap (Heap A)]) (Heap A)]{ 72 | Function @scheme[delete-min/max] takes a bootstrapped heap and returns the 73 | same heap without the min or max element in the given heap. The element 74 | removed from the heap is max or min depends on the comparison function of the 75 | heap. 76 | @examples[#:eval evaluate 77 | 78 | (delete-min/max (heap < 1 2 3 4 5 6)) 79 | (delete-min/max (heap > 1 2 3 4 5 6)) 80 | (delete-min/max (heap <)) 81 | 82 | ] 83 | 84 | In the above example, 85 | @scheme[(delete-min/max (heap < 1 2 3 4 5 6))], deletes element 86 | 1 from @scheme[(heap < 1 2 3 4 5 6)]. And 87 | @scheme[(delete-min/max (heap > 1 2 3 4 5 6))], deletes element 88 | 6 from @scheme[(heap > 1 2 3 4 5 6)].} 89 | 90 | @defproc[(merge [heap1 (Heap A)] [heap2 (Heap A)]) (Heap A)]{ 91 | Function @scheme[merge] takes two bootstrapped heaps and returns a 92 | merged bootstrapped heap. Uses the comparison function in the first heap for 93 | merging and the same function becomes the comparison function for the 94 | merged heap. 95 | 96 | @margin-note{If the comparison 97 | functions do not have the same properties, merged heap might lose its 98 | heap-order.} 99 | 100 | @examples[#:eval evaluate 101 | 102 | (define bheap1 (heap < 1 2 3 4 5 6)) 103 | (define bheap2 (heap (λ: ([a : Integer] 104 | [b : Integer]) 105 | (< a b)) 106 | 10 20 30 40 50 60)) 107 | (merge bheap1 bheap2) 108 | 109 | ] 110 | 111 | In the above example, @scheme[(merge bheap1 bheap2)], merges the heaps and 112 | < will become the comparison function for the merged heap. 113 | } 114 | 115 | 116 | 117 | @defproc[(sorted-list [heap (Heap A)]) (Listof A)]{ 118 | Function @scheme[sorted-list] takes a bootstrapped heap and returns a 119 | list which is sorted according to the comparison function of the heap. 120 | 121 | @examples[#:eval evaluate 122 | 123 | (sorted-list (heap > 1 2 3 4 5 6)) 124 | (sorted-list (heap < 1 2 3 4 5 6)) 125 | ] 126 | 127 | In the above example, @scheme[(sorted-list bheap)], returns 128 | @scheme[(6 5 4 3 2 1)].} 129 | 130 | @defproc[(map [comparer (C C -> Boolean)] 131 | [func (A B ... B -> C)] 132 | [hep1 (Heap A)] 133 | [hep2 (Heap B)] ...) (Heap A)]{ 134 | Function @scheme[map] is similar to @|racket-map| for lists. 135 | @examples[#:eval evaluate 136 | 137 | (sorted-list (map < add1 (heap < 1 2 3 4 5 6))) 138 | 139 | (sorted-list (map < * (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6))) 140 | ]} 141 | 142 | @defproc[(fold [func (C A B ... B -> C)] 143 | [init C] 144 | [hep1 (Heap A)] 145 | [hep2 (Heap B)] ...) C]{ 146 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 147 | @margin-note{@scheme[fold] currently does not produce correct results when the 148 | given function is non-commutative.} 149 | 150 | @examples[#:eval evaluate 151 | 152 | (fold + 0 (heap < 1 2 3 4 5 6)) 153 | 154 | (fold * 1 (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6)) 155 | ]} 156 | 157 | @defproc[(filter [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 158 | Function @scheme[filter] is similar to @|racket-filter|. 159 | @examples[#:eval evaluate 160 | 161 | (define hep (heap < 1 2 3 4 5 6)) 162 | 163 | (sorted-list (filter (λ: ([x : Integer]) (> x 5)) hep)) 164 | 165 | (sorted-list (filter (λ: ([x : Integer]) (< x 5)) hep)) 166 | 167 | (sorted-list (filter (λ: ([x : Integer]) (<= x 5)) hep)) 168 | ]} 169 | 170 | @defproc[(remove [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 171 | Function @scheme[remove] is similar to @|racket-filter| but 172 | @scheme[remove] removes the elements which match the predicate. 173 | @examples[#:eval evaluate 174 | 175 | (sorted-list (remove (λ: ([x : Integer]) (> x 5)) 176 | (heap < 1 2 3 4 5 6))) 177 | 178 | (sorted-list (remove (λ: ([x : Integer]) (< x 5)) 179 | (heap < 1 2 3 4 5 6))) 180 | 181 | (sorted-list (remove (λ: ([x : Integer]) (<= x 5)) 182 | (heap < 1 2 3 4 5 6))) 183 | ]} 184 | 185 | @defproc[(andmap [func (A B ... B -> Boolean)] 186 | [heap1 (Heap A)] 187 | [heap2 (Heap B)] ...) Boolean]{ 188 | Function @scheme[andmap] is similar to @|racket-andmap|. 189 | 190 | @examples[#:eval evaluate 191 | 192 | (andmap even? (heap < 1 2 3 4 5 6)) 193 | 194 | (andmap odd? (heap < 1 2 3 4 5 6)) 195 | 196 | (andmap positive? (heap < 1 2 3 4 5 6)) 197 | 198 | (andmap negative? (heap < -1 -2)) 199 | ]} 200 | 201 | 202 | @defproc[(ormap [func (A B ... B -> Boolean)] 203 | [heap1 (Heap A)] 204 | [heap2 (Heap B)] ...) Boolean]{ 205 | Function @scheme[ormap] is similar to @|racket-ormap|. 206 | 207 | @examples[#:eval evaluate 208 | 209 | (ormap even? (heap < 1 2 3 4 5 6)) 210 | 211 | (ormap odd? (heap < 1 2 3 4 5 6)) 212 | 213 | (ormap positive? (heap < -1 -2 3 4 -5 6)) 214 | 215 | (ormap negative? (heap < 1 -2)) 216 | ]} 217 | 218 | @defproc[(build-heap [size Natural] 219 | [func (Natural -> A)] 220 | [comp (A A -> Boolean)]) 221 | (Heap A)]{ 222 | Function @scheme[build-heap] is similar to @|racket-build-list| but this 223 | function takes an extra comparison function. 224 | 225 | @examples[#:eval evaluate 226 | 227 | (sorted-list (build-heap 5 (λ:([x : Integer]) (add1 x)) <)) 228 | 229 | (sorted-list (build-heap 5 (λ:([x : Integer]) (* x x)) <)) 230 | 231 | ]} 232 | 233 | @(close-eval evaluate) 234 | -------------------------------------------------------------------------------- /pfds/scribblings/bootstrapedqueue.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/queue/bootstrapped)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/queue/bootstrapped)) 9 | 10 | @title[#:tag "boot-que"]{Bootstraped Queue} 11 | 12 | @defmodule[pfds/queue/bootstrapped] 13 | 14 | Bootstrapped Queue use a structural bootstrapping technique called 15 | @italic{Structural Decomposition}. The data structure gives a worst 16 | case running time of @bold{@italic{O(1)}} for the operation 17 | @scheme[head] and @bold{@italic{O(log*(n))}} for 18 | @scheme[tail] and @scheme[enqueue]. Internally uses @secref["phy-que"]. 19 | 20 | @;section{Bootstraped Queue Construction and Operations} 21 | @defform[(Queue A)]{A bootstrapped queue of type @racket[A].} 22 | 23 | @defproc[(queue [a A] ...) (Queue A)]{ 24 | Function @scheme[queue] creates a Bootstraped Queue with the 25 | given inputs. 26 | @examples[#:eval evaluate 27 | 28 | (queue 1 2 3 4 5 6) 29 | ] 30 | 31 | In the above example, the queue obtained will have 1 as its first element.} 32 | 33 | 34 | @defthing[empty (Queue Nothing)]{ 35 | An empty queue.} 36 | 37 | @defproc[(empty? [que (Queue A)]) Boolean]{ 38 | Function @scheme[empty?] checks if the given queue is empty or not. 39 | 40 | @examples[#:eval evaluate 41 | 42 | (empty? (queue 1 2 3 4 5 6)) 43 | 44 | (empty? empty) 45 | ]} 46 | 47 | @defproc[(enqueue [a A] [que (Queue A)]) (Queue A)]{ 48 | Function @scheme[enqueue] takes an element and a queue and enqueues 49 | the given element into the queue. 50 | @examples[#:eval evaluate 51 | 52 | (enqueue 10 (queue 1 2 3 4 5 6)) 53 | 54 | ] 55 | 56 | In the above example, @scheme[(enqueue 10 (queue 1 2 3 4 5 6))] adds the 57 | 10 to the queue @scheme[(queue 1 2 3 4 5 6)]. 10 as its last element.} 58 | 59 | @defproc[(head [que (Queue A)]) A]{ 60 | Function @scheme[head] takes a queue and gives the first element in the 61 | queue if queue is not empty else throws an error. 62 | @examples[#:eval evaluate 63 | 64 | (head (queue 1 2 3 4 5 6)) 65 | (head empty) 66 | ]} 67 | 68 | @defproc[(tail [que (Queue A)]) (Queue A)]{ 69 | Function @scheme[tail] takes a queue and returns the same queue without 70 | the first element of the given queue if its a non empty queue else throws an 71 | error. 72 | @examples[#:eval evaluate 73 | 74 | (tail (queue 1 2 3 4 5 6)) 75 | 76 | (tail empty) 77 | ] 78 | 79 | In the above example, @scheme[(tail (queue 1 2 3 4 5 6))], removes the head of 80 | the given queue returns @scheme[(queue 2 3 4 5 6)].} 81 | 82 | 83 | @defproc[(queue->list [que (Queue A)]) (Queue A)]{ 84 | Function @scheme[queue->list] takes a queue and returns a list of 85 | elements. The list will have head of the given queue as its first element. 86 | If the given queue is empty, then it returns an empty list. 87 | 88 | @examples[#:eval evaluate 89 | 90 | (queue->list (queue 10 2 34 4 15 6)) 91 | (queue->list empty) 92 | ]} 93 | 94 | @defproc[(map [func (A B ... B -> C)] 95 | [que1 (Queue A)] 96 | [que2 (Queue B)] ...) (Queue A)]{ 97 | Function @scheme[map] is similar to @|racket-map| for lists. 98 | @examples[#:eval evaluate 99 | 100 | (queue->list (map add1 (queue 1 2 3 4 5 6))) 101 | 102 | (queue->list (map * (queue 1 2 3 4 5 6) (queue 1 2 3 4 5 6))) 103 | ]} 104 | 105 | @defproc[(fold [func (C A B ... B -> C)] 106 | [init C] 107 | [que1 (Queue A)] 108 | [que2 (Queue B)] ...) C]{ 109 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 110 | @margin-note{@scheme[fold] currently does not produce correct results when the 111 | given function is non-commutative.} 112 | 113 | @examples[#:eval evaluate 114 | 115 | (fold + 0 (queue 1 2 3 4 5 6)) 116 | 117 | (fold * 1 (queue 1 2 3 4 5 6) (queue 1 2 3 4 5 6)) 118 | ]} 119 | 120 | @defproc[(filter [func (A -> Boolean)] [que (Queue A)]) (Queue A)]{ 121 | Function @scheme[filter] is similar to @|racket-filter|. 122 | @examples[#:eval evaluate 123 | 124 | (define que (queue 1 2 3 4 5 6)) 125 | 126 | (queue->list (filter (λ: ([x : Integer]) (> x 5)) que)) 127 | 128 | (queue->list (filter (λ: ([x : Integer]) (< x 5)) que)) 129 | 130 | (queue->list (filter (λ: ([x : Integer]) (<= x 5)) que)) 131 | ]} 132 | 133 | @defproc[(remove [func (A -> Boolean)] [que (Queue A)]) (Queue A)]{ 134 | Function @scheme[remove] is similar to @|racket-filter| but 135 | @scheme[remove] removes the elements which match the predicate. 136 | @examples[#:eval evaluate 137 | 138 | (queue->list (remove (λ: ([x : Integer]) (> x 5)) 139 | (queue 1 2 3 4 5 6))) 140 | 141 | (queue->list (remove (λ: ([x : Integer]) (< x 5)) 142 | (queue 1 2 3 4 5 6))) 143 | 144 | (queue->list (remove (λ: ([x : Integer]) (<= x 5)) 145 | (queue 1 2 3 4 5 6))) 146 | ]} 147 | 148 | 149 | @defproc[(andmap [func (A B ... B -> Boolean)] 150 | [que1 (Queue A)] 151 | [que2 (Queue B)] ...) Boolean]{ 152 | Function @scheme[andmap] is similar to @|racket-andmap|. 153 | 154 | @examples[#:eval evaluate 155 | 156 | (andmap even? (queue 1 2 3 4 5 6)) 157 | 158 | (andmap odd? (queue 1 2 3 4 5 6)) 159 | 160 | (andmap positive? (queue 1 2 3 4 5 6)) 161 | 162 | (andmap negative? (queue -1 -2)) 163 | ]} 164 | 165 | 166 | @defproc[(ormap [func (A B ... B -> Boolean)] 167 | [que1 (Queue A)] 168 | [que2 (Queue B)] ...) Boolean]{ 169 | Function @scheme[ormap] is similar to @|racket-ormap|. 170 | 171 | @examples[#:eval evaluate 172 | 173 | (ormap even? (queue 1 2 3 4 5 6)) 174 | 175 | (ormap odd? (queue 1 2 3 4 5 6)) 176 | 177 | (ormap positive? (queue -1 -2 3 4 -5 6)) 178 | 179 | (ormap negative? (queue 1 -2)) 180 | ]} 181 | 182 | @defproc[(build-queue [size Natural] 183 | [func (Natural -> A)]) 184 | (Queue A)]{ 185 | Function @scheme[build-queue] is similar to @|racket-build-list|. 186 | @examples[#:eval evaluate 187 | 188 | (queue->list (build-queue 5 (λ:([x : Integer]) (add1 x)))) 189 | 190 | (queue->list (build-queue 5 (λ:([x : Integer]) (* x x)))) 191 | 192 | ]} 193 | 194 | @defproc[(head+tail [que (Queue A)]) 195 | (Pair A (Queue A))]{ 196 | Function @scheme[head+tail] returns a pair containing the head and the tail of 197 | the given queue. 198 | @examples[#:eval evaluate 199 | 200 | (head+tail (queue 1 2 3 4 5)) 201 | 202 | (head+tail (build-queue 5 (λ:([x : Integer]) (* x x)))) 203 | 204 | (head+tail empty) 205 | 206 | ]} 207 | 208 | @(close-eval evaluate) 209 | -------------------------------------------------------------------------------- /pfds/scribblings/catenable-list.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/catenable-list)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/catenable-list)) 9 | 10 | @title{Catenable List} 11 | 12 | @defmodule[pfds/catenable-list] 13 | 14 | Catenable lists are a list-like data structure with efficient catenation. They 15 | use a bootstrapping technique called @italic{structucal abstraction}. The data 16 | structure internally uses @secref["boot-que"] to realize an amortized running 17 | time of @bold{@italic{O(1)}} for the operations @scheme[first], @scheme[rest], 18 | @scheme[cons] and @scheme[cons-to-end]. 19 | 20 | @defform[(CatenableList A)]{A catenable list of type @racket[A].} 21 | 22 | @defproc[(list [a A] ...) (CatenableList A)]{ 23 | Function list creates a catenable list with the given inputs. 24 | 25 | @examples[#:eval evaluate 26 | 27 | (list 1 2 3 4 5 6) 28 | ] 29 | 30 | In the above example, @scheme[(list 1 2 3 4 5 6)] gives a Catenable List 31 | which is similar to lists but comes with efficient append operation.} 32 | 33 | @defform/none[empty]{ 34 | A empty catenable list.} 35 | 36 | @defproc[(empty? [catlist (CatenableList A)]) Boolean]{ 37 | Function @scheme[empty?] takes a Catenable List checks if the given catenable 38 | list is empty. 39 | @examples[#:eval evaluate 40 | 41 | (empty? (list 1 2 3 4 5 6)) 42 | 43 | (empty? empty) 44 | 45 | ]} 46 | 47 | @defproc[(cons [a A] [catlist (CatenableList A)]) (CatenableList A)]{ 48 | Function @scheme[cons] takes an element and a catenable list and adds 49 | the given element to the front the given catenable list. 50 | @examples[#:eval evaluate 51 | 52 | (cons 10 (list 1 2 3 4 5 6)) 53 | ] 54 | 55 | In the above example, @scheme[(cons 10 (list 1 2 3 4 5 6))] returns 56 | @scheme[(list 10 1 2 3 4 5 6)].} 57 | 58 | 59 | @defproc[(cons-to-end [a A] [catlist (CatenableList A)]) (CatenableList A)]{ 60 | Function @scheme[cons-to-end] takes an element and a catenable list and adds 61 | the given element to the rear end the given catenable list. 62 | @examples[#:eval evaluate 63 | 64 | (cons-to-end 10 (list 1 2 3 4 5 6)) 65 | ] 66 | 67 | In the above example, @scheme[(cons-to-end 10 (list 1 2 3 4 5 6))] returns 68 | @scheme[(list 1 2 3 4 5 6 10)].} 69 | 70 | @defproc[(first [catlist (CatenableList A)]) A]{ 71 | Function @scheme[first] takes a catenable list and returns the first element 72 | of the given catenable list. 73 | @examples[#:eval evaluate 74 | 75 | (first (list 1 2 3 4 5 6)) 76 | (first empty) 77 | ]} 78 | 79 | 80 | @defproc[(rest [catlist (CatenableList A)]) (CatenableList A)]{ 81 | Function @scheme[rest] takes a catenable list and returns a catenable list 82 | without the first element of the given catenable list. 83 | @examples[#:eval evaluate 84 | 85 | (rest (list 1 2 3 4 5 6)) 86 | (rest empty) 87 | ] 88 | 89 | In the above example, @scheme[(rest (list 1 2 3 4 5 6))] returns the rest of 90 | the given catenable list, @scheme[(list 2 3 4 5 6)].} 91 | 92 | 93 | @defproc[(append [cal1 (CatenableList A)] [cal2 (CatenableList A)]) 94 | (CatenableList A)]{ 95 | Function @scheme[append] takes two catenable lists and appends the second 96 | catenable list to the end of the first catenable list. 97 | 98 | 99 | @examples[#:eval evaluate 100 | 101 | (define cal1 (list 1 2 3 4 5 6)) 102 | (define cal2 (list 7 8 9 10)) 103 | 104 | (append cal1 cal2) 105 | ] 106 | 107 | In the above example, @scheme[(append cal1 cal2)] returns 108 | @scheme[(list 1 2 3 4 5 6 7 8 9 10)].} 109 | 110 | 111 | @defproc[(->list [cal (CatenableList A)]) (Listof A)]{ 112 | Function @scheme[->list] takes a clist and returns a list 113 | of elements which are in the same order as in the catenable list. 114 | @examples[#:eval evaluate 115 | 116 | (->list (list 1 2 3 4 5 6)) 117 | 118 | (->list empty) 119 | ]} 120 | 121 | @defproc[(reverse [cal (List A)]) (List A)]{ 122 | Function @scheme[reverse] takes a vlist and returns a reversed vlist. 123 | 124 | @examples[#:eval evaluate 125 | 126 | (->list (reverse (list 1 2 3 4 5 6))) 127 | ]} 128 | 129 | @defproc[(map [func (A B ... B -> C)] 130 | [clst1 (CatenableList A)] 131 | [clst2 (CatenableList B)] ...) (CatenableList A)]{ 132 | Function @scheme[map] is similar to @|racket-map| for lists. 133 | @examples[#:eval evaluate 134 | 135 | (->list (map add1 (list 1 2 3 4 5 6))) 136 | 137 | (->list (map * (list 1 2 3 4 5 6) (list 1 2 3 4 5 6))) 138 | ]} 139 | 140 | @defproc[(foldl [func (C A B ... B -> C)] 141 | [init C] 142 | [clst1 (CatenableList A)] 143 | [clst2 (CatenableList B)] ...) C]{ 144 | Function @scheme[foldl] is similar to @|racket-foldl| 145 | @margin-note{@scheme[foldl] currently does not produce correct results when the 146 | given function is non-commutative.} 147 | 148 | @examples[#:eval evaluate 149 | 150 | (foldl + 0 (list 1 2 3 4 5 6)) 151 | 152 | (foldl * 1 (list 1 2 3 4 5 6) (list 1 2 3 4 5 6)) 153 | ]} 154 | 155 | @defproc[(foldr [func (C A B ... B -> C)] 156 | [init C] 157 | [clst1 (CatenableList A)] 158 | [clst2 (CatenableList B)] ...) C]{ 159 | Function @scheme[foldr] is similar to @|racket-foldr| 160 | @margin-note{@scheme[foldr] currently does not produce correct results when the 161 | given function is non-commutative.} 162 | 163 | @examples[#:eval evaluate 164 | 165 | (foldr + 0 (list 1 2 3 4 5 6)) 166 | 167 | (foldr * 1 (list 1 2 3 4 5 6) (list 1 2 3 4 5 6)) 168 | ]} 169 | 170 | 171 | @defproc[(andmap [func (A B ... B -> Boolean)] 172 | [lst1 (CatenableList A)] 173 | [lst2 (CatenableList B)] ...) Boolean]{ 174 | Function @scheme[andmap] is similar to @|racket-andmap|. 175 | 176 | @examples[#:eval evaluate 177 | 178 | (andmap even? (list 1 2 3 4 5 6)) 179 | 180 | (andmap odd? (list 1 2 3 4 5 6)) 181 | 182 | (andmap positive? (list 1 2 3 4 5 6)) 183 | 184 | (andmap negative? (list -1 -2)) 185 | ]} 186 | 187 | 188 | @defproc[(ormap [func (A B ... B -> Boolean)] 189 | [lst1 (CatenableList A)] 190 | [lst2 (CatenableList B)] ...) Boolean]{ 191 | Function @scheme[ormap] is similar to @|racket-ormap|. 192 | 193 | @examples[#:eval evaluate 194 | 195 | (ormap even? (list 1 2 3 4 5 6)) 196 | 197 | (ormap odd? (list 1 2 3 4 5 6)) 198 | 199 | (ormap positive? (list -1 -2 3 4 -5 6)) 200 | 201 | (ormap negative? (list 1 -2)) 202 | ]} 203 | 204 | @defproc[(build-list [size Natural] 205 | [func (Natural -> A)]) 206 | (CatenableList A)]{ 207 | Function @scheme[build-list] is similar to @|racket-build-list|. 208 | @examples[#:eval evaluate 209 | 210 | (->list (build-list 5 (λ:([x : Integer]) (add1 x)))) 211 | 212 | (->list (build-list 5 (λ:([x : Integer]) (* x x)))) 213 | 214 | ]} 215 | 216 | @defproc[(make-list [size Natural] 217 | [func A]) 218 | (CatenableList A)]{ 219 | Function @scheme[make-list] is similar to @|racket-make-list|. 220 | @examples[#:eval evaluate 221 | 222 | (->list (make-list 5 10)) 223 | 224 | (->list (make-list 5 'sym)) 225 | 226 | ]} 227 | 228 | @defproc[(filter [func (A -> Boolean)] [que (CatenableList A)]) (CatenableList A)]{ 229 | Function @scheme[filter] is similar to @|racket-filter|. 230 | @examples[#:eval evaluate 231 | 232 | (define que (list 1 2 3 4 5 6)) 233 | 234 | (->list (filter (λ: ([x : Integer]) (> x 5)) que)) 235 | 236 | (->list (filter (λ: ([x : Integer]) (< x 5)) que)) 237 | 238 | (->list (filter (λ: ([x : Integer]) (<= x 5)) que)) 239 | ]} 240 | 241 | @defproc[(remove [func (A -> Boolean)] [que (CatenableList A)]) (CatenableList A)]{ 242 | Function @scheme[remove] is similar to @|racket-filter| but @scheme[remove] removes the elements which match the predicate. 243 | @examples[#:eval evaluate 244 | 245 | (->list (remove (λ: ([x : Integer]) (> x 5)) 246 | (list 1 2 3 4 5 6))) 247 | 248 | (->list (remove (λ: ([x : Integer]) (< x 5)) 249 | (list 1 2 3 4 5 6))) 250 | 251 | (->list (remove (λ: ([x : Integer]) (<= x 5)) 252 | (list 1 2 3 4 5 6))) 253 | ]} 254 | 255 | @(close-eval evaluate) 256 | -------------------------------------------------------------------------------- /pfds/scribblings/deques.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @title{Deques} 4 | 5 | Double ended queues (or deque) are queues where elements can be added or 6 | removed from either end. The deque data structures provided by this library 7 | implement and provide the following operations: deque, empty?, enqueue, 8 | enqueue-front, head, tail, last, init and deque->list. 9 | 10 | @local-table-of-contents[] 11 | @include-section{bankers-deque.scrbl} 12 | @include-section{implicitdeque.scrbl} 13 | @include-section{realtimedeque.scrbl} 14 | -------------------------------------------------------------------------------- /pfds/scribblings/functional-data-structures.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @title[#:tag "top"]{Functional Data Structures in Typed Racket} 4 | The data structures in this library are based on the work of 5 | Chris Okasaki and Phil Bagwell, including those in the 6 | @italic{Purely Functional Data Structures} by Okasaki. 7 | All of the data structures are implemented in Typed Racket. 8 | 9 | @author[@link["http://www.ccs.neu.edu/home/krhari"]{Hari Prashanth K R}] 10 | 11 | @local-table-of-contents[] 12 | 13 | @include-section{queues.scrbl} 14 | @include-section{deques.scrbl} 15 | @include-section{heaps.scrbl} 16 | @include-section{randomaccesslist.scrbl} 17 | @;@include-section{catenable-list.scrbl} 18 | @include-section{vlist.scrbl} 19 | @include-section{streams.scrbl} 20 | @include-section{redblacktrees.scrbl} 21 | @include-section{tries.scrbl} 22 | @include-section{treap.scrbl} 23 | -------------------------------------------------------------------------------- /pfds/scribblings/heaps.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @title{Heaps} 4 | Following heap structures implement and provide the functions 5 | empty?, insert, find-min/max, delete-min/max, merge and sorted-list. 6 | All the heaps are polymorphic. 7 | 8 | @local-table-of-contents[] 9 | @include-section{binomialheap.scrbl} 10 | @include-section{skewbinomialheap.scrbl} 11 | @include-section{leftistheap.scrbl} 12 | @include-section{splayheap.scrbl} 13 | @include-section{pairingheap.scrbl} 14 | @include-section{lazypairingheap.scrbl} 15 | @include-section{bootstrapedheap.scrbl} 16 | -------------------------------------------------------------------------------- /pfds/scribblings/helper.rkt: -------------------------------------------------------------------------------- 1 | #lang at-exp racket/base 2 | (require scribble/manual 3 | (for-label racket/base) 4 | scribble/eval) 5 | 6 | (define racket-map @racket[map]) 7 | (define racket-foldl @racket[foldl]) 8 | (define racket-foldr @racket[foldr]) 9 | (define racket-filter @racket[filter]) 10 | (define racket-remove @racket[remove]) 11 | (define racket-andmap @racket[andmap]) 12 | (define racket-ormap @racket[ormap]) 13 | (define racket-build-list @racket[build-list]) 14 | (define racket-make-list @racket[make-list]) 15 | (provide racket-map racket-foldl racket-foldr racket-filter racket-remove 16 | racket-andmap racket-ormap racket-build-list racket-make-list 17 | make-base-eval examples close-eval) 18 | -------------------------------------------------------------------------------- /pfds/scribblings/hood-melville-queue.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/queue/hood-melville)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/queue/hood-melville)) 9 | 10 | @title{Hood-Melville Queue} 11 | 12 | @defmodule[pfds/queue/hood-melville] 13 | 14 | Similar to real-time queues in many ways. But the implementation is 15 | much more complicated than Real-Time Queue. Uses a technique called 16 | @italic{Global Rebuilding}. The data structure gives a worst case 17 | running time of @bold{@italic{O(1)}} for the operations 18 | @scheme[head], @scheme[tail] and @scheme[enqueue]. 19 | 20 | @;section{Hood-Melville Construction and Operations} 21 | 22 | @defform[(Queue A)]{A Hood-Melville queue of type @racket[A].} 23 | 24 | @defproc[(queue [a A] ...) (Queue A)]{ 25 | Function @scheme[queue] creates a Hood-Melville with the 26 | given inputs. 27 | @examples[#:eval evaluate 28 | 29 | (queue 1 2 3 4 5 6) 30 | ] 31 | 32 | In the above example, the queue obtained will have 1 as its head element.} 33 | 34 | 35 | @defthing[empty (Queue Nothing)]{ 36 | An empty queue.} 37 | 38 | @defproc[(empty? [que (Queue A)]) Boolean]{ 39 | Function @scheme[empty?] checks if the given queue is empty or not. 40 | 41 | @examples[#:eval evaluate 42 | 43 | (empty? (queue 1 2 3 4 5 6)) 44 | 45 | (empty? empty) 46 | ]} 47 | 48 | @defproc[(enqueue [a A] [que (Queue A)]) (Queue A)]{ 49 | Function @scheme[enqueue] takes an element and a queue and enqueues 50 | the given element into the queue. 51 | @examples[#:eval evaluate 52 | 53 | (enqueue 10 (queue 1 2 3 4 5 6)) 54 | ] 55 | 56 | In the above example, enqueue adds the element 10 to 57 | @scheme[(queue 1 2 3 4 5 6)] and returns @scheme[(queue 1 2 3 4 5 6 10)].} 58 | 59 | @defproc[(head [que (Queue A)]) A]{ 60 | Function @scheme[head] takes a queue and gives the first element in the 61 | queue if queue is not empty else throws an error. 62 | @examples[#:eval evaluate 63 | 64 | (head (queue 1 2 3 4 5 6)) 65 | (head empty) 66 | ]} 67 | 68 | @defproc[(tail [que (Queue A)]) (Queue A)]{ 69 | Function @scheme[tail] takes a queue and returns a queue with rest 70 | elements if its a non empty queue else throws an error. 71 | @examples[#:eval evaluate 72 | 73 | (tail (queue 1 2 3 4 5 6)) 74 | 75 | (tail empty) 76 | ] 77 | 78 | In the above example, @scheme[(tail (queue 1 2 3 4 5 6))], returns 79 | @scheme[(queue 2 3 4 5 6)].} 80 | 81 | 82 | @defproc[(queue->list [que (Queue A)]) (Queue A)]{ 83 | Function @scheme[queue->list] takes a queue and returns a list of 84 | elements. The list will have head of the given queue as its first element. 85 | If the given queue is empty, then it returns an empty list. 86 | For 87 | @examples[#:eval evaluate 88 | 89 | (queue->list (queue 10 2 34 4 15 6)) 90 | (queue->list empty) 91 | ]} 92 | 93 | @defproc[(map [func (A B ... B -> C)] 94 | [que1 (Queue A)] 95 | [que2 (Queue B)] ...) (Queue A)]{ 96 | Function @scheme[map] is similar to @|racket-map| for lists. 97 | @examples[#:eval evaluate 98 | 99 | (queue->list (map add1 (queue 1 2 3 4 5 6))) 100 | 101 | (queue->list (map * (queue 1 2 3 4 5 6) (queue 1 2 3 4 5 6))) 102 | ]} 103 | 104 | @defproc[(fold [func (C A B ... B -> C)] 105 | [init C] 106 | [que1 (Queue A)] 107 | [que2 (Queue B)] ...) C]{ 108 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 109 | @margin-note{@scheme[fold] currently does not produce correct results when the 110 | given function is non-commutative.} 111 | 112 | @examples[#:eval evaluate 113 | 114 | (fold + 0 (queue 1 2 3 4 5 6)) 115 | 116 | (fold * 1 (queue 1 2 3 4 5 6) (queue 1 2 3 4 5 6)) 117 | ]} 118 | 119 | @defproc[(filter [func (A -> Boolean)] [que (Queue A)]) (Queue A)]{ 120 | Function @scheme[filter] is similar to @|racket-filter|. 121 | @examples[#:eval evaluate 122 | 123 | (define que (queue 1 2 3 4 5 6)) 124 | 125 | (queue->list (filter (λ: ([x : Integer]) (> x 5)) que)) 126 | 127 | (queue->list (filter (λ: ([x : Integer]) (< x 5)) que)) 128 | 129 | (queue->list (filter (λ: ([x : Integer]) (<= x 5)) que)) 130 | ]} 131 | 132 | @defproc[(remove [func (A -> Boolean)] [que (Queue A)]) (Queue A)]{ 133 | Function @scheme[remove] is similar to @|racket-filter| but 134 | @scheme[remove] removes the elements which match the predicate. 135 | @examples[#:eval evaluate 136 | 137 | (queue->list (remove (λ: ([x : Integer]) (> x 5)) 138 | (queue 1 2 3 4 5 6))) 139 | 140 | (queue->list (remove (λ: ([x : Integer]) (< x 5)) 141 | (queue 1 2 3 4 5 6))) 142 | 143 | (queue->list (remove (λ: ([x : Integer]) (<= x 5)) 144 | (queue 1 2 3 4 5 6))) 145 | ]} 146 | 147 | @defproc[(andmap [func (A B ... B -> Boolean)] 148 | [que1 (Queue A)] 149 | [que2 (Queue B)] ...) Boolean]{ 150 | Function @scheme[andmap] is similar to @|racket-andmap|. 151 | 152 | @examples[#:eval evaluate 153 | 154 | (andmap even? (queue 1 2 3 4 5 6)) 155 | 156 | (andmap odd? (queue 1 2 3 4 5 6)) 157 | 158 | (andmap positive? (queue 1 2 3 4 5 6)) 159 | 160 | (andmap negative? (queue -1 -2)) 161 | ]} 162 | 163 | 164 | @defproc[(ormap [func (A B ... B -> Boolean)] 165 | [que1 (Queue A)] 166 | [que2 (Queue B)] ...) Boolean]{ 167 | Function @scheme[ormap] is similar to @|racket-ormap|. 168 | 169 | @examples[#:eval evaluate 170 | 171 | (ormap even? (queue 1 2 3 4 5 6)) 172 | 173 | (ormap odd? (queue 1 2 3 4 5 6)) 174 | 175 | (ormap positive? (queue -1 -2 3 4 -5 6)) 176 | 177 | (ormap negative? (queue 1 -2)) 178 | ]} 179 | 180 | @defproc[(build-queue [size Natural] 181 | [func (Natural -> A)]) 182 | (Queue A)]{ 183 | Function @scheme[build-queue] is similar to @|racket-build-list|. 184 | @examples[#:eval evaluate 185 | 186 | (queue->list (build-queue 5 (λ:([x : Integer]) (add1 x)))) 187 | 188 | (queue->list (build-queue 5 (λ:([x : Integer]) (* x x)))) 189 | 190 | ]} 191 | 192 | @defproc[(head+tail [que (Queue A)]) 193 | (Pair A (Queue A))]{ 194 | Function @scheme[head+tail] returns a pair containing the head and the tail of 195 | the given queue. 196 | @examples[#:eval evaluate 197 | 198 | (head+tail (queue 1 2 3 4 5)) 199 | 200 | (head+tail (build-queue 5 (λ:([x : Integer]) (* x x)))) 201 | 202 | (head+tail empty) 203 | 204 | ]} 205 | 206 | @(close-eval evaluate) 207 | -------------------------------------------------------------------------------- /pfds/scribblings/implicitqueue.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/queue/implicit)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/queue/implicit)) 9 | 10 | @title{Implicit Queue} 11 | 12 | @defmodule[pfds/queue/implicit] 13 | 14 | Queues obtained by applying the technique called 15 | @italic{Implicit Recursive Slowdown}. Provides a amortized 16 | running time of @bold{@italic{O(1)}} for the operations 17 | @scheme[head], @scheme[tail] and @scheme[enqueue]. 18 | Implicit Recursive Slowdown combines 19 | laziness and technique called Recursive Slow-Down developed by 20 | @italic{Kaplan and Tarjan} in their paper 21 | @italic{Persistant Lists with Catenation via Recursive Slow-Down}. 22 | 23 | @;section{Implicit Queue Construction and Operations} 24 | 25 | @defform[(Queue A)]{A implicit queue of type @racket[A].} 26 | 27 | @defproc[(queue [a A] ...) (Queue A)]{ 28 | Function @scheme[queue] creates a Implicit Queue with the 29 | given inputs. 30 | @examples[#:eval evaluate 31 | 32 | (queue 1 2 3 4 5 6) 33 | ] 34 | 35 | In the above example, the queue obtained will have 1 as its head element.} 36 | 37 | 38 | @defthing[empty (Queue Nothing)]{ 39 | An empty queue.} 40 | 41 | @defproc[(empty? [que (Queue A)]) Boolean]{ 42 | Function @scheme[empty?] checks if the given queue is empty or not. 43 | 44 | @examples[#:eval evaluate 45 | 46 | (empty? (queue 1 2 3 4 5 6)) 47 | 48 | (empty? empty) 49 | ]} 50 | 51 | @defproc[(enqueue [a A] [que (Queue A)]) (Queue A)]{ 52 | Function@scheme[enqueue] takes an element and a queue and enqueues 53 | the given element into the queue. 54 | @examples[#:eval evaluate 55 | 56 | (enqueue 10 (queue 1 2 3 4 5 6)) 57 | ] 58 | 59 | In the above example, enqueue adds the element 10 to 60 | of @scheme[(queue 1 2 3 4 5 6)] and returns @scheme[(queue 1 2 3 4 5 6 10)].} 61 | 62 | @defproc[(head [que (Queue A)]) A]{ 63 | Function @scheme[head] takes a queue and gives the first element in the 64 | queue if queue is not empty else throws an error. 65 | @examples[#:eval evaluate 66 | 67 | (head (queue 1 2 3 4 5 6)) 68 | (head empty) 69 | ]} 70 | 71 | @defproc[(tail [que (Queue A)]) (Queue A)]{ 72 | Function @scheme[tail] takes a queue and returns a queue with rest 73 | elements if its a non empty queue else throws an error. 74 | @examples[#:eval evaluate 75 | 76 | (tail (queue 1 2 3 4 5 6)) 77 | (tail empty) 78 | ] 79 | In the above example, @scheme[(tail (queue 1 2 3 4 5 6))], removes the head of 80 | the given queue returns @scheme[(queue 2 3 4 5 6)].} 81 | 82 | 83 | @defproc[(queue->list [que (Queue A)]) (Queue A)]{ 84 | Function @scheme[queue->list] takes a queue and returns a list of 85 | elements. The list will have head of the given queue as its first element. 86 | If the given queue is empty, then it returns an empty list. 87 | 88 | @examples[#:eval evaluate 89 | 90 | (queue->list (queue 10 2 34 4 15 6)) 91 | (queue->list empty) 92 | ]} 93 | 94 | @defproc[(map [func (A B ... B -> C)] 95 | [que1 (Queue A)] 96 | [que2 (Queue B)] ...) (Queue A)]{ 97 | Function @scheme[map] is similar to @|racket-map| for lists. 98 | @examples[#:eval evaluate 99 | 100 | (queue->list (map add1 (queue 1 2 3 4 5 6))) 101 | 102 | (queue->list (map * (queue 1 2 3 4 5 6) (queue 1 2 3 4 5 6))) 103 | ]} 104 | 105 | @defproc[(fold [func (C A B ... B -> C)] 106 | [init C] 107 | [que1 (Queue A)] 108 | [que2 (Queue B)] ...) C]{ 109 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 110 | @margin-note{@scheme[fold] currently does not produce correct results when the 111 | given function is non-commutative.} 112 | 113 | @examples[#:eval evaluate 114 | 115 | (fold + 0 (queue 1 2 3 4 5 6)) 116 | 117 | (fold * 1 (queue 1 2 3 4 5 6) (queue 1 2 3 4 5 6)) 118 | ]} 119 | 120 | @defproc[(filter [func (A -> Boolean)] [que (Queue A)]) (Queue A)]{ 121 | Function @scheme[filter] is similar to @|racket-filter|. 122 | @examples[#:eval evaluate 123 | 124 | (define que (queue 1 2 3 4 5 6)) 125 | 126 | (queue->list (filter (λ: ([x : Integer]) (> x 5)) que)) 127 | 128 | (queue->list (filter (λ: ([x : Integer]) (< x 5)) que)) 129 | 130 | (queue->list (filter (λ: ([x : Integer]) (<= x 5)) que)) 131 | ]} 132 | 133 | @defproc[(remove [func (A -> Boolean)] [que (Queue A)]) (Queue A)]{ 134 | Function @scheme[remove] is similar to @|racket-filter| but @scheme[remove] removes the elements which match the predicate. 135 | @examples[#:eval evaluate 136 | 137 | (queue->list (remove (λ: ([x : Integer]) (> x 5)) 138 | (queue 1 2 3 4 5 6))) 139 | 140 | (queue->list (remove (λ: ([x : Integer]) (< x 5)) 141 | (queue 1 2 3 4 5 6))) 142 | 143 | (queue->list (remove (λ: ([x : Integer]) (<= x 5)) 144 | (queue 1 2 3 4 5 6))) 145 | ]} 146 | 147 | 148 | @defproc[(andmap [func (A B ... B -> Boolean)] 149 | [que1 (Queue A)] 150 | [que2 (Queue B)] ...) Boolean]{ 151 | Function @scheme[andmap] is similar to @|racket-andmap|. 152 | 153 | @examples[#:eval evaluate 154 | 155 | (andmap even? (queue 1 2 3 4 5 6)) 156 | 157 | (andmap odd? (queue 1 2 3 4 5 6)) 158 | 159 | (andmap positive? (queue 1 2 3 4 5 6)) 160 | 161 | (andmap negative? (queue -1 -2)) 162 | ]} 163 | 164 | 165 | @defproc[(ormap [func (A B ... B -> Boolean)] 166 | [que1 (Queue A)] 167 | [que2 (Queue B)] ...) Boolean]{ 168 | Function @scheme[ormap] is similar to @|racket-ormap|. 169 | 170 | @examples[#:eval evaluate 171 | 172 | (ormap even? (queue 1 2 3 4 5 6)) 173 | 174 | (ormap odd? (queue 1 2 3 4 5 6)) 175 | 176 | (ormap positive? (queue -1 -2 3 4 -5 6)) 177 | 178 | (ormap negative? (queue 1 -2)) 179 | ]} 180 | 181 | @defproc[(build-queue [size Natural] 182 | [func (Natural -> A)]) 183 | (Queue A)]{ 184 | Function @scheme[build-queue] is similar to @|racket-build-list|. 185 | @examples[#:eval evaluate 186 | 187 | (queue->list (build-queue 5 (λ:([x : Integer]) (add1 x)))) 188 | 189 | (queue->list (build-queue 5 (λ:([x : Integer]) (* x x)))) 190 | 191 | ]} 192 | 193 | @defproc[(head+tail [que (Queue A)]) 194 | (Pair A (Queue A))]{ 195 | Function @scheme[head+tail] returns a pair containing the head and the tail of 196 | the given queue. 197 | @examples[#:eval evaluate 198 | 199 | (head+tail (queue 1 2 3 4 5)) 200 | 201 | (head+tail (build-queue 5 (λ:([x : Integer]) (* x x)))) 202 | 203 | (head+tail empty) 204 | 205 | ]} 206 | 207 | 208 | @(close-eval evaluate) 209 | -------------------------------------------------------------------------------- /pfds/scribblings/lazypairingheap.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/heap/lazy-pairing)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/heap/lazy-pairing)) 9 | 10 | @title{Lazy Pairing Heap} 11 | 12 | @defmodule[pfds/heap/lazy-pairing] 13 | 14 | Lazy Pairing Heap is very similar to Pairing Heap. The only difference between 15 | the two is, as the name suggests, Lazy Pairing Heap is lazy in nature. 16 | 17 | @defform[(Heap A)]{A lazy pairing heap of type @racket[A].} 18 | 19 | @defproc[(heap [comp (A A -> Boolean)] [a A] ...) (Heap A)]{ 20 | Function @scheme[heap] creates a Lazy Pairing Heap with the given 21 | inputs. 22 | @examples[#:eval evaluate 23 | 24 | (heap < 1 2 3 4 5 6) 25 | ] 26 | 27 | In the above example, the lazy pairing heap obtained will have elements 1 thru' 6 28 | with < as the comparison function.} 29 | 30 | 31 | @;subsection{empty} 32 | @;An empty lazy pairing heap. 33 | 34 | @defproc[(empty? [heap (Heap A)]) Boolean]{ 35 | Function @scheme[empty?] checks if the given lazy pairing heap is empty or not. 36 | 37 | @examples[#:eval evaluate 38 | 39 | (empty? (heap < 1 2 3 4 5 6)) 40 | 41 | (empty? (heap <)) 42 | ]} 43 | 44 | 45 | @defproc[(insert [a A] [heap (Heap A)] ...) (Heap A)]{ 46 | Function @scheme[insert] takes an element and a lazy pairing heap and inserts 47 | the given element into the lazy pairing heap. 48 | @examples[#:eval evaluate 49 | 50 | (insert 10 (heap < 1 2 3 4 5 6)) 51 | ] 52 | 53 | In the above example, @scheme[(insert 10 (heap < 1 2 3 4 5 6))] 54 | adds the element 10 to the heap @scheme[(heap < 1 2 3 4 5 6)].} 55 | 56 | @defproc[(find-min/max [heap (Heap A)]) A]{ 57 | Function @scheme[find-min/max] takes a lazy pairing heap and gives the 58 | largest or the smallest element in the heap if lazy pairing heap is not empty 59 | else throws an error. The element returned is max or min depends on the 60 | comparison function of the heap. 61 | @examples[#:eval evaluate 62 | 63 | (find-min/max (heap < 1 2 3 4 5 6)) 64 | (find-min/max (heap > 1 2 3 4 5 6)) 65 | (find-min/max (heap <)) 66 | ]} 67 | 68 | @defproc[(delete-min/max [heap (Heap A)]) (Heap A)]{ 69 | Function @scheme[delete-min/max] takes a lazy pairing heap and returns the 70 | same heap with out the min or max element in the given heap. The element 71 | removed from the heap is max or min depends on the comparison function of the 72 | heap. 73 | @examples[#:eval evaluate 74 | 75 | (delete-min/max (heap < 1 2 3 4 5 6)) 76 | (delete-min/max (heap > 1 2 3 4 5 6)) 77 | (delete-min/max (heap >)) 78 | ]} 79 | 80 | @defproc[(merge [pheap1 (Heap A)] [pheap2 (Heap A)]) (Heap A)]{ 81 | Function @scheme[merge] takes two lazy pairing heaps and returns a 82 | merged lazy pairing heap. Uses the comparison function in the first heap for 83 | merging and the same function becomes the comparison function for the 84 | merged heap. 85 | 86 | @margin-note{If the comparison 87 | functions do not have the same properties, merged heap might lose its 88 | heap-order.} 89 | 90 | @examples[#:eval evaluate 91 | 92 | (define pheap1 (heap < 1 2 3 4 5 6)) 93 | (define pheap2 (heap (λ: ([a : Integer] 94 | [b : Integer]) 95 | (< a b)) 96 | 10 20 30 40 50 60)) 97 | (merge pheap1 pheap2) 98 | 99 | ] 100 | 101 | In the above example, @scheme[(merge pheap1 pheap2)], merges the heaps and 102 | < will become the comparison function for the merged heap.} 103 | 104 | 105 | 106 | @defproc[(sorted-list [heap (Heap A)]) (Listof A)]{ 107 | Function @scheme[sorted-list] takes a lazy pairing heap and returns a list 108 | which is sorted according to the comparison function of the heap. 109 | @examples[#:eval evaluate 110 | 111 | (sorted-list (heap > 1 2 3 4 5 6)) 112 | (sorted-list (heap < 1 2 3 4 5 6)) 113 | ]} 114 | 115 | @defproc[(map [comparer (C C -> Boolean)] 116 | [func (A B ... B -> C)] 117 | [hep1 (Heap A)] 118 | [hep2 (Heap B)] ...) (Heap A)]{ 119 | Function @scheme[map] is similar to @|racket-map| for lists. 120 | @examples[#:eval evaluate 121 | 122 | (sorted-list (map < add1 (heap < 1 2 3 4 5 6))) 123 | 124 | (sorted-list (map < * (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6))) 125 | ]} 126 | 127 | @defproc[(fold [func (C A B ... B -> C)] 128 | [init C] 129 | [hep1 (Heap A)] 130 | [hep2 (Heap B)] ...) C]{ 131 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 132 | @margin-note{@scheme[fold] currently does not produce correct results when the 133 | given function is non-commutative.} 134 | 135 | @examples[#:eval evaluate 136 | 137 | (fold + 0 (heap < 1 2 3 4 5 6)) 138 | 139 | (fold * 1 (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6)) 140 | ]} 141 | 142 | @defproc[(filter [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 143 | Function @scheme[filter] is similar to @|racket-filter|. 144 | @examples[#:eval evaluate 145 | 146 | (define hep (heap < 1 2 3 4 5 6)) 147 | 148 | (sorted-list (filter (λ: ([x : Integer]) (> x 5)) hep)) 149 | 150 | (sorted-list (filter (λ: ([x : Integer]) (< x 5)) hep)) 151 | 152 | (sorted-list (filter (λ: ([x : Integer]) (<= x 5)) hep)) 153 | ]} 154 | 155 | @defproc[(remove [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 156 | Function @scheme[remove] is similar to @|racket-filter| but 157 | @scheme[remove] removes the elements which match the predicate. 158 | @examples[#:eval evaluate 159 | 160 | (sorted-list (remove (λ: ([x : Integer]) (> x 5)) 161 | (heap < 1 2 3 4 5 6))) 162 | 163 | (sorted-list (remove (λ: ([x : Integer]) (< x 5)) 164 | (heap < 1 2 3 4 5 6))) 165 | 166 | (sorted-list (remove (λ: ([x : Integer]) (<= x 5)) 167 | (heap < 1 2 3 4 5 6))) 168 | ]} 169 | 170 | @defproc[(andmap [func (A B ... B -> Boolean)] 171 | [heap1 (Heap A)] 172 | [heap2 (Heap B)] ...) Boolean]{ 173 | Function @scheme[andmap] is similar to @|racket-andmap|. 174 | 175 | @examples[#:eval evaluate 176 | 177 | (andmap even? (heap < 1 2 3 4 5 6)) 178 | 179 | (andmap odd? (heap < 1 2 3 4 5 6)) 180 | 181 | (andmap positive? (heap < 1 2 3 4 5 6)) 182 | 183 | (andmap negative? (heap < -1 -2)) 184 | ]} 185 | 186 | 187 | @defproc[(ormap [func (A B ... B -> Boolean)] 188 | [heap1 (Heap A)] 189 | [heap2 (Heap B)] ...) Boolean]{ 190 | Function @scheme[ormap] is similar to @|racket-ormap|. 191 | 192 | @examples[#:eval evaluate 193 | 194 | (ormap even? (heap < 1 2 3 4 5 6)) 195 | 196 | (ormap odd? (heap < 1 2 3 4 5 6)) 197 | 198 | (ormap positive? (heap < -1 -2 3 4 -5 6)) 199 | 200 | (ormap negative? (heap < 1 -2)) 201 | ]} 202 | 203 | @defproc[(build-heap [size Natural] 204 | [func (Natural -> A)] 205 | [comp (A A -> Boolean)]) 206 | (Heap A)]{ 207 | Function @scheme[build-heap] is similar to @|racket-build-list| but this 208 | function takes an extra comparison function. 209 | 210 | @examples[#:eval evaluate 211 | 212 | (sorted-list (build-heap 5 (λ:([x : Integer]) (add1 x)) <)) 213 | 214 | (sorted-list (build-heap 5 (λ:([x : Integer]) (* x x)) <)) 215 | 216 | ]} 217 | 218 | @(close-eval evaluate) 219 | -------------------------------------------------------------------------------- /pfds/scribblings/leftistheap.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/heap/leftist)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/heap/leftist)) 9 | 10 | @title{Leftist Heap} 11 | 12 | @defmodule[pfds/heap/leftist] 13 | 14 | Leftist heaps are heap-ordered binary trees that satisfy the 15 | leftist property: the rank of any left child is at least as large as the rank 16 | of its right sibling. The rank of a node is defined to be the length of its 17 | right spine (i.e., the rightmost path from the node in question to an empty 18 | node). A simple consequence of the leftist property is that the right spine 19 | of any node is always the shortest path to an empty node. 20 | 21 | Provides worst case running time of @bold{@italic{O(log(n))}} for the 22 | operations @scheme[insert], @scheme[delete-min/max] and @scheme[merge] 23 | and a worst case running 24 | time of @bold{@italic{O(1)}} for @scheme[find-min/max]. 25 | 26 | @defform[(Heap A)]{A leftist heap of type @racket[A].} 27 | 28 | @defproc[(heap [comp (A A -> Boolean)] [a A] ...) (Heap A)]{ 29 | Function @scheme[heap] creates a Leftist Heap with the given 30 | inputs. 31 | @examples[#:eval evaluate 32 | 33 | (heap < 1 2 3 4 5 6) 34 | ] 35 | 36 | In the above example, the leftist heap obtained will have elements 1 thru' 6 37 | with < as the comparison function.} 38 | 39 | 40 | @defproc[(empty? [heap (Heap A)]) Boolean]{ 41 | Function @scheme[empty?] checks if the given leftist heap is empty or not. 42 | 43 | @examples[#:eval evaluate 44 | 45 | (empty? (heap < 1 2 3 4 5 6)) 46 | 47 | (empty? empty) 48 | ]} 49 | 50 | @defproc[(insert [a A] [heap (Heap A)] ...) (Heap A)]{ 51 | Function @scheme[insert] takes an element and a leftist heap and inserts 52 | the given element into the leftist heap. 53 | @examples[#:eval evaluate 54 | 55 | (insert 10 (heap < 1 2 3 4 5 6)) 56 | ] 57 | 58 | In the above example, insert adds the element 10 to the heap 59 | @scheme[(heap < 1 2 3 4 5 6)].} 60 | 61 | @defproc[(find-min/max [heap (Heap A)]) A]{ 62 | Function @scheme[find-min/max] takes a leftist heap and gives the 63 | largest or the smallest element in the heap if leftist heap is not empty 64 | else throws an error. The element returned is max or min depends on the 65 | comparison function of the heap. 66 | @examples[#:eval evaluate 67 | 68 | (find-min/max (heap < 1 2 3 4 5 6)) 69 | (find-min/max (heap > 1 2 3 4 5 6)) 70 | (find-min/max (heap <)) 71 | ] 72 | 73 | In the above example, @scheme[(find-min/max lheap)], returns the smallest 74 | element in @scheme[lheap] which happens to be 1.} 75 | 76 | @defproc[(delete-min/max [heap (Heap A)]) (Heap A)]{ 77 | Function @scheme[delete-min/max] takes a leftist heap and returns the 78 | same heap with out the min or max element in the given heap. The element 79 | removed from the heap is max or min depends on the comparison function of the 80 | heap. 81 | @examples[#:eval evaluate 82 | 83 | (delete-min/max (heap < 1 2 3 4 5 6)) 84 | (delete-min/max (heap > 1 2 3 4 5 6)) 85 | (delete-min/max (heap <)) 86 | ] 87 | 88 | In the above example, @scheme[(delete-min/max (heap < 1 2 3 4 5 6))] 89 | deletes min element 1 from the heap and 90 | @scheme[(delete-min/max (heap > 1 2 3 4 5 6))] deletes max element 6 91 | from the heap.} 92 | 93 | @defproc[(merge [lheap1 (Heap A)] [lheap2 (Heap A)]) (Heap A)]{ 94 | Function @scheme[merge] takes two leftist heaps and returns a 95 | merged leftist heap. Uses the comparison function in the first heap for 96 | merging and the same function becomes the comparison function for the 97 | merged heap. 98 | 99 | @margin-note{If the comparison 100 | functions do not have the same properties, merged heap might lose its 101 | heap-order.} 102 | 103 | @examples[#:eval evaluate 104 | 105 | (define lheap1 (heap < 1 2 3 4 5 6)) 106 | (define lheap2 (heap (λ: ([a : Integer] 107 | [b : Integer]) 108 | (< a b)) 109 | 10 20 30 40 50 60)) 110 | (merge lheap1 lheap2) 111 | 112 | ] 113 | 114 | In the above example, @scheme[(merge lheap1 lheap2)], merges the heaps and 115 | < will become the comparison function for the merged heap.} 116 | 117 | 118 | @defproc[(sorted-list [heap (Heap A)]) (Listof A)]{ 119 | Function @scheme[sorted-list] takes a leftist heap and returns a list 120 | which is sorted according to the comparison function of the heap. 121 | @examples[#:eval evaluate 122 | 123 | (sorted-list (heap > 1 2 3 4 5 6)) 124 | (sorted-list (heap < 1 2 3 4 5 6)) 125 | ]} 126 | 127 | @defproc[(map [comparer (C C -> Boolean)] 128 | [func (A B ... B -> C)] 129 | [hep1 (Heap A)] 130 | [hep2 (Heap B)] ...) (Heap A)]{ 131 | Function @scheme[map] is similar to @|racket-map| for lists. 132 | @examples[#:eval evaluate 133 | 134 | (sorted-list (map < add1 (heap < 1 2 3 4 5 6))) 135 | 136 | (sorted-list (map < * (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6))) 137 | ]} 138 | 139 | @defproc[(fold [func (C A B ... B -> C)] 140 | [init C] 141 | [hep1 (Heap A)] 142 | [hep2 (Heap B)] ...) C]{ 143 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 144 | @margin-note{@scheme[fold] currently does not produce correct results when the 145 | given function is non-commutative.} 146 | 147 | @examples[#:eval evaluate 148 | 149 | (fold + 0 (heap < 1 2 3 4 5 6)) 150 | 151 | (fold * 1 (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6)) 152 | ]} 153 | 154 | @defproc[(filter [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 155 | Function @scheme[filter] is similar to @|racket-filter|. 156 | @examples[#:eval evaluate 157 | 158 | (define hep (heap < 1 2 3 4 5 6)) 159 | 160 | (sorted-list (filter (λ: ([x : Integer]) (> x 5)) hep)) 161 | 162 | (sorted-list (filter (λ: ([x : Integer]) (< x 5)) hep)) 163 | 164 | (sorted-list (filter (λ: ([x : Integer]) (<= x 5)) hep)) 165 | ]} 166 | 167 | @defproc[(remove [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 168 | Function @scheme[remove] is similar to @|racket-filter| but @scheme[remove] removes the elements which match the predicate. 169 | @examples[#:eval evaluate 170 | 171 | (sorted-list (remove (λ: ([x : Integer]) (> x 5)) 172 | (heap < 1 2 3 4 5 6))) 173 | 174 | (sorted-list (remove (λ: ([x : Integer]) (< x 5)) 175 | (heap < 1 2 3 4 5 6))) 176 | 177 | (sorted-list (remove (λ: ([x : Integer]) (<= x 5)) 178 | (heap < 1 2 3 4 5 6))) 179 | ]} 180 | 181 | @defproc[(andmap [func (A B ... B -> Boolean)] 182 | [heap1 (Heap A)] 183 | [heap2 (Heap B)] ...) Boolean]{ 184 | Function @scheme[andmap] is similar to @|racket-andmap|. 185 | 186 | @examples[#:eval evaluate 187 | 188 | (andmap even? (heap < 1 2 3 4 5 6)) 189 | 190 | (andmap odd? (heap < 1 2 3 4 5 6)) 191 | 192 | (andmap positive? (heap < 1 2 3 4 5 6)) 193 | 194 | (andmap negative? (heap < -1 -2)) 195 | ]} 196 | 197 | 198 | @defproc[(ormap [func (A B ... B -> Boolean)] 199 | [heap1 (Heap A)] 200 | [heap2 (Heap B)] ...) Boolean]{ 201 | Function @scheme[ormap] is similar to @|racket-ormap|. 202 | 203 | @examples[#:eval evaluate 204 | 205 | (ormap even? (heap < 1 2 3 4 5 6)) 206 | 207 | (ormap odd? (heap < 1 2 3 4 5 6)) 208 | 209 | (ormap positive? (heap < -1 -2 3 4 -5 6)) 210 | 211 | (ormap negative? (heap < 1 -2)) 212 | ]} 213 | 214 | @defproc[(build-heap [size Natural] 215 | [func (Natural -> A)] 216 | [comp (A A -> Boolean)]) 217 | (Heap A)]{ 218 | Function @scheme[build-heap] is similar to @|racket-build-list| but this 219 | function takes an extra comparison function. 220 | 221 | @examples[#:eval evaluate 222 | 223 | (sorted-list (build-heap 5 (λ:([x : Integer]) (add1 x)) <)) 224 | 225 | (sorted-list (build-heap 5 (λ:([x : Integer]) (* x x)) <)) 226 | 227 | ]} 228 | 229 | @(close-eval evaluate) 230 | -------------------------------------------------------------------------------- /pfds/scribblings/pairingheap.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/heap/pairing)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/heap/pairing)) 9 | 10 | @title{Pairing Heap} 11 | 12 | @defmodule[pfds/heap/pairing] 13 | 14 | Pairing Heap is a type of heap which has a very simple implementation 15 | and has extremely good performance in practice. Pairing Heaps provide a 16 | worst case running time of @bold{@italic{O(1)}} for the operations 17 | @scheme[insert] @scheme[find-min/max] @scheme[merge]. 18 | And @scheme[delete-min/max] has a amortized 19 | running time of @bold{@italic{O(log(n))}}. 20 | 21 | @defform[(Heap A)]{A pairing heap of type @racket[A].} 22 | 23 | @defproc[(heap [comp (A A -> Boolean)] [a A] ...) (Heap A)]{ 24 | Function @scheme[heap] creates a Pairing Heap with the given 25 | inputs. 26 | @examples[#:eval evaluate 27 | 28 | (heap < 1 2 3 4 5 6) 29 | ] 30 | 31 | In the above example, the pairing heap obtained will have elements 1 thru' 6 32 | with < as the comparison function.} 33 | 34 | 35 | @defproc[(empty? [heap (Heap A)]) Boolean]{ 36 | Function @scheme[empty?] checks if the given pairing heap is empty or not. 37 | 38 | @examples[#:eval evaluate 39 | 40 | (empty? (heap < 1 2 3 4 5 6)) 41 | 42 | (empty? (heap <)) 43 | ]} 44 | 45 | @defproc[(insert [a A] [heap (Heap A)] ...) (Heap A)]{ 46 | Function @scheme[insert] takes an element and a pairing heap and inserts 47 | the given element into the pairing heap. 48 | @examples[#:eval evaluate 49 | 50 | (insert 10 (heap < 1 2 3 4 5 6)) 51 | ] 52 | 53 | In the above example, @scheme[(insert 10 (heap < 1 2 3 4 5 6))] adds 54 | the element 10 to @scheme[(heap < 1 2 3 4 5 6)].} 55 | 56 | @defproc[(find-min/max [heap (Heap A)]) A]{ 57 | Function @scheme[find-min/max] takes a pairing heap and gives the 58 | largest or the smallest element in the heap if pairing heap is not empty 59 | else throws an error. The element returned is max or min depends on the 60 | comparison function of the heap. For 61 | @examples[#:eval evaluate 62 | 63 | (find-min/max (heap < 1 2 3 4 5 6)) 64 | (find-min/max (heap > 1 2 3 4 5 6)) 65 | (find-min/max (heap >)) 66 | ]} 67 | 68 | @defproc[(delete-min/max [heap (Heap A)]) (Heap A)]{ 69 | Function @scheme[delete-min/max] takes a pairing heap and returns the 70 | same heap with out the min or max element in the given heap. The element 71 | removed from the heap is max or min depends on the comparison function of the 72 | heap. For 73 | @examples[#:eval evaluate 74 | 75 | (delete-min/max (heap < 1 2 3 4 5 6)) 76 | (delete-min/max (heap > 1 2 3 4 5 6)) 77 | (delete-min/max (heap <)) 78 | ] 79 | 80 | In the above example, @scheme[(delete-min/max (heap < 1 2 3 4 5 6))], 81 | deletes the smallest element 1 in the heap @scheme[(heap < 1 2 3 4 5 6)]. 82 | And @scheme[(delete-min/max (heap > 1 2 3 4 5 6))] deletes the largest 83 | element which is 6.} 84 | 85 | @defproc[(merge [pheap1 (Heap A)] [pheap2 (Heap A)]) (Heap A)]{ 86 | Function @scheme[merge] takes two pairing heaps and returns a 87 | merged pairing heap. Uses the comparison function in the first heap for 88 | merging and the same function becomes the comparison function for the 89 | merged heap. 90 | 91 | @margin-note{If the comparison 92 | functions do not have the same properties, merged heap might lose its 93 | heap-order.} 94 | 95 | @examples[#:eval evaluate 96 | 97 | (define pheap1 (heap < 1 2 3 4 5 6)) 98 | (define pheap2 (heap (λ: ([a : Integer] 99 | [b : Integer]) 100 | (< a b)) 101 | 10 20 30 40 50 60)) 102 | (merge pheap1 pheap2) 103 | 104 | ] 105 | 106 | In the above example, @scheme[(merge pheap1 pheap2)], merges the heaps and 107 | < will become the comparison function for the merged heap.} 108 | 109 | 110 | 111 | @defproc[(sorted-list [heap (Heap A)]) (Listof A)]{ 112 | Function @scheme[sorted-list] takes a pairing heap and returns a list 113 | which is sorted according to the comparison function of the heap. For 114 | @examples[#:eval evaluate 115 | 116 | (sorted-list (heap > 1 2 3 4 5 6)) 117 | (sorted-list (heap < 1 2 3 4 5 6)) 118 | ]} 119 | 120 | @defproc[(map [comparer (C C -> Boolean)] 121 | [func (A B ... B -> C)] 122 | [hep1 (Heap A)] 123 | [hep2 (Heap B)] ...) (Heap A)]{ 124 | Function @scheme[map] is similar to @|racket-map| for lists. 125 | @examples[#:eval evaluate 126 | 127 | (sorted-list (map < add1 (heap < 1 2 3 4 5 6))) 128 | 129 | (sorted-list (map < * (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6))) 130 | ]} 131 | 132 | @defproc[(fold [func (C A B ... B -> C)] 133 | [init C] 134 | [hep1 (Heap A)] 135 | [hep2 (Heap B)] ...) C]{ 136 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 137 | @margin-note{@scheme[fold] currently does not produce correct results when the 138 | given function is non-commutative.} 139 | 140 | @examples[#:eval evaluate 141 | 142 | (fold + 0 (heap < 1 2 3 4 5 6)) 143 | 144 | (fold * 1 (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6)) 145 | ]} 146 | 147 | @defproc[(filter [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 148 | Function @scheme[filter] is similar to @|racket-filter|. 149 | @examples[#:eval evaluate 150 | 151 | (define hep (heap < 1 2 3 4 5 6)) 152 | 153 | (sorted-list (filter (λ: ([x : Integer]) (> x 5)) hep)) 154 | 155 | (sorted-list (filter (λ: ([x : Integer]) (< x 5)) hep)) 156 | 157 | (sorted-list (filter (λ: ([x : Integer]) (<= x 5)) hep)) 158 | ]} 159 | 160 | @defproc[(remove [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 161 | Function @scheme[remove] is similar to @|racket-filter| but @scheme[remove] removes the elements which match the predicate. 162 | @examples[#:eval evaluate 163 | 164 | (sorted-list (remove (λ: ([x : Integer]) (> x 5)) 165 | (heap < 1 2 3 4 5 6))) 166 | 167 | (sorted-list (remove (λ: ([x : Integer]) (< x 5)) 168 | (heap < 1 2 3 4 5 6))) 169 | 170 | (sorted-list (remove (λ: ([x : Integer]) (<= x 5)) 171 | (heap < 1 2 3 4 5 6))) 172 | ]} 173 | 174 | @defproc[(andmap [func (A B ... B -> Boolean)] 175 | [heap1 (Heap A)] 176 | [heap2 (Heap B)] ...) Boolean]{ 177 | Function @scheme[andmap] is similar to @|racket-andmap|. 178 | 179 | @examples[#:eval evaluate 180 | 181 | (andmap even? (heap < 1 2 3 4 5 6)) 182 | 183 | (andmap odd? (heap < 1 2 3 4 5 6)) 184 | 185 | (andmap positive? (heap < 1 2 3 4 5 6)) 186 | 187 | (andmap negative? (heap < -1 -2)) 188 | ]} 189 | 190 | 191 | @defproc[(ormap [func (A B ... B -> Boolean)] 192 | [heap1 (Heap A)] 193 | [heap2 (Heap B)] ...) Boolean]{ 194 | Function @scheme[ormap] is similar to @|racket-ormap|. 195 | 196 | @examples[#:eval evaluate 197 | 198 | (ormap even? (heap < 1 2 3 4 5 6)) 199 | 200 | (ormap odd? (heap < 1 2 3 4 5 6)) 201 | 202 | (ormap positive? (heap < -1 -2 3 4 -5 6)) 203 | 204 | (ormap negative? (heap < 1 -2)) 205 | ]} 206 | 207 | @defproc[(build-heap [size Natural] 208 | [func (Natural -> A)] 209 | [comp (A A -> Boolean)]) 210 | (Heap A)]{ 211 | Function @scheme[build-heap] is similar to @|racket-build-list| but this 212 | function takes an extra comparison function. 213 | 214 | @examples[#:eval evaluate 215 | 216 | (sorted-list (build-heap 5 (λ:([x : Integer]) (add1 x)) <)) 217 | 218 | (sorted-list (build-heap 5 (λ:([x : Integer]) (* x x)) <)) 219 | 220 | ]} 221 | 222 | @(close-eval evaluate) 223 | -------------------------------------------------------------------------------- /pfds/scribblings/physicists-queue.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/queue/physicists)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/queue/physicists)) 9 | 10 | @title[#:tag "phy-que"]{Physicist's Queue} 11 | 12 | @defmodule[pfds/queue/physicists] 13 | 14 | A Queue is nothing but a FIFO data structure. A Physicist's queue ia a 15 | Amortized queues obtained by Physicist's method. Provides a amortized 16 | running time of @bold{@italic{O(1)}} for @scheme[head], @scheme[tail] 17 | and @scheme[enqueue] operations. Physicists's Queue uses lazy evaluation 18 | and memoization to get this amortized running time. 19 | 20 | @;section{Physicist's Queue Construction and Operations} 21 | @defform[(Queue A)]{A physicist's queue of type @racket[A].} 22 | 23 | 24 | @defproc[(queue [a A] ...) (Queue A)]{ 25 | Function @scheme[queue] creates a Physicist's Queue with the given inputs. 26 | 27 | @examples[#:eval evaluate 28 | 29 | (queue 1 2 3 4 5 6) 30 | ] 31 | 32 | In the above example, the queue obtained will have 1 as its head element} 33 | 34 | 35 | @defproc[(empty [t A]) (Queue A)]{ 36 | An empty queue.} 37 | 38 | @defproc[(empty? [que (Queue A)]) Boolean]{ 39 | Function @scheme[empty?] checks if the given queue is empty or not. 40 | 41 | @examples[#:eval evaluate 42 | 43 | (empty? (queue 1 2 3 4 5 6)) 44 | 45 | (empty? (empty Integer)) 46 | ]} 47 | 48 | 49 | @defproc[(enqueue [a A] [que (Queue A)]) (Queue A)]{ 50 | Function @scheme[enqueue] takes an element and a queue and enqueues 51 | the given element into the queue. 52 | @examples[#:eval evaluate 53 | 54 | (enqueue 10 (queue 1 2 3 4 5 6)) 55 | ] 56 | 57 | In the above example, enqueue adds the element 10 to 58 | @scheme[(queue 1 2 3 4 5 6)] and returns @scheme[(queue 1 2 3 4 5 6 10)].} 59 | 60 | @defproc[(head [que (Queue A)]) A]{ 61 | Function @scheme[head] takes a queue and gives the first element in the 62 | queue if its a non empty queue else throws an error. 63 | @examples[#:eval evaluate 64 | 65 | (head (queue 1 2 3 4 5 6)) 66 | (head (empty Integer)) 67 | ]} 68 | 69 | @defproc[(tail [que (Queue A)]) (Queue A)]{ 70 | Function @scheme[tail] takes a queue and returns a queue with rest 71 | elements if its a non empty queue else throws an error. 72 | @examples[#:eval evaluate 73 | 74 | (tail (queue 1 2 3 4 5 6)) 75 | 76 | (tail (empty Integer)) 77 | ] 78 | 79 | In the above example, @scheme[(tail (queue 1 2 3 4 5 6))], returns 80 | @scheme[(queue 2 3 4 5 6)].} 81 | 82 | 83 | @defproc[(queue->list [que (Queue A)]) (Queue A)]{ 84 | Function @scheme[queue->list] takes a queue and returns a list of 85 | elements. The list will have head of the given queue as its first element. 86 | If the given queue is empty, then it returns an empty list. 87 | 88 | @examples[#:eval evaluate 89 | 90 | (queue->list (queue 10 2 34 4 15 6)) 91 | 92 | (queue->list (empty Integer)) 93 | ]} 94 | 95 | 96 | @; 97 | @;subsection{list->queue} 98 | @;Function @scheme[list->queue] takes a list and returns a queue of 99 | @;elements. The queue will be such that its head will have car of the list. 100 | 101 | @;examples[#:eval evaluate 102 | 103 | @;(list->queue (list 10 2 34 4 15 6)) 104 | 105 | @;] 106 | 107 | @;In the above example, @scheme[(list->queue (list 10 2 34 4 15 6))], returns 108 | @;the queue @scheme[(queue 10 2 34 4 15 6)]. 109 | @; 110 | 111 | @defproc[(map [func (A B ... B -> C)] 112 | [que1 (Queue A)] 113 | [que2 (Queue B)] ...) (Queue A)]{ 114 | Function @scheme[map] is similar to @|racket-map| for lists. 115 | @examples[#:eval evaluate 116 | 117 | (queue->list (map add1 (queue 1 2 3 4 5 6))) 118 | 119 | (queue->list (map * (queue 1 2 3 4 5 6) (queue 1 2 3 4 5 6))) 120 | ]} 121 | 122 | @defproc[(fold [func (C A B ... B -> C)] 123 | [init C] 124 | [que1 (Queue A)] 125 | [que2 (Queue B)] ...) C]{ 126 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 127 | @margin-note{@scheme[fold] currently does not produce correct results when the 128 | given function is non-commutative.} 129 | 130 | @examples[#:eval evaluate 131 | 132 | (fold + 0 (queue 1 2 3 4 5 6)) 133 | 134 | (fold * 1 (queue 1 2 3 4 5 6) (queue 1 2 3 4 5 6)) 135 | ]} 136 | 137 | @defproc[(filter [func (A -> Boolean)] [que (Queue A)]) (Queue A)]{ 138 | Function @scheme[filter] is similar to @|racket-filter|. 139 | @examples[#:eval evaluate 140 | 141 | (define que (queue 1 2 3 4 5 6)) 142 | 143 | (queue->list (filter (λ: ([x : Integer]) (> x 5)) que)) 144 | 145 | (queue->list (filter (λ: ([x : Integer]) (< x 5)) que)) 146 | 147 | (queue->list (filter (λ: ([x : Integer]) (<= x 5)) que)) 148 | ]} 149 | 150 | @defproc[(remove [func (A -> Boolean)] [que (Queue A)]) (Queue A)]{ 151 | Function @scheme[remove] is similar to @|racket-filter| but @scheme[remove] removes the elements which match the predicate. 152 | @examples[#:eval evaluate 153 | 154 | (queue->list (remove (λ: ([x : Integer]) (> x 5)) 155 | (queue 1 2 3 4 5 6))) 156 | 157 | (queue->list (remove (λ: ([x : Integer]) (< x 5)) 158 | (queue 1 2 3 4 5 6))) 159 | 160 | (queue->list (remove (λ: ([x : Integer]) (<= x 5)) 161 | (queue 1 2 3 4 5 6))) 162 | ]} 163 | 164 | 165 | @defproc[(andmap [func (A B ... B -> Boolean)] 166 | [que1 (Queue A)] 167 | [que2 (Queue B)] ...) Boolean]{ 168 | Function @scheme[andmap] is similar to @|racket-andmap|. 169 | 170 | @examples[#:eval evaluate 171 | 172 | (andmap even? (queue 1 2 3 4 5 6)) 173 | 174 | (andmap odd? (queue 1 2 3 4 5 6)) 175 | 176 | (andmap positive? (queue 1 2 3 4 5 6)) 177 | 178 | (andmap negative? (queue -1 -2)) 179 | ]} 180 | 181 | 182 | @defproc[(ormap [func (A B ... B -> Boolean)] 183 | [que1 (Queue A)] 184 | [que2 (Queue B)] ...) Boolean]{ 185 | Function @scheme[ormap] is similar to @|racket-ormap|. 186 | 187 | @examples[#:eval evaluate 188 | 189 | (ormap even? (queue 1 2 3 4 5 6)) 190 | 191 | (ormap odd? (queue 1 2 3 4 5 6)) 192 | 193 | (ormap positive? (queue -1 -2 3 4 -5 6)) 194 | 195 | (ormap negative? (queue 1 -2)) 196 | ]} 197 | 198 | @defproc[(build-queue [size Natural] 199 | [func (Natural -> A)]) 200 | (Queue A)]{ 201 | Function @scheme[build-queue] is similar to @|racket-build-list|. 202 | @examples[#:eval evaluate 203 | 204 | (queue->list (build-queue 5 (λ:([x : Integer]) (add1 x)))) 205 | 206 | (queue->list (build-queue 5 (λ:([x : Integer]) (* x x)))) 207 | 208 | ]} 209 | 210 | @defproc[(head+tail [que (Queue A)]) 211 | (Pair A (Queue A))]{ 212 | Function @scheme[head+tail] returns a pair containing the head and the tail of 213 | the given queue. 214 | @examples[#:eval evaluate 215 | 216 | (head+tail (queue 1 2 3 4 5)) 217 | 218 | (head+tail (build-queue 5 (λ:([x : Integer]) (* x x)))) 219 | 220 | (head+tail (empty Integer)) 221 | 222 | ]} 223 | 224 | @(close-eval evaluate) 225 | -------------------------------------------------------------------------------- /pfds/scribblings/queue.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/queue/bankers)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/queue/bankers)) 9 | 10 | @title{Banker's Queue} 11 | 12 | @defmodule[pfds/queue/bankers] 13 | 14 | A Queue is nothing but a FIFO data structure. A Banker's Queue is a 15 | amortized queue obtained using Bankers method. It provides a amortized 16 | running time of @bold{@italic{O(1)}} for @scheme[head], @scheme[tail] 17 | and @scheme[enqueue] operations. To obtain this amortized running time, 18 | the data structure uses the techniques, lazy evaluation and 19 | memoization. Banker's Queue internally uses Streams for lazy 20 | evaluation. For Streams, see @secref["streams"] 21 | 22 | @defform[(Queue A)]{A banker's queue of type @racket[A].} 23 | 24 | @defproc[(queue [a A] ...) (Queue A)]{ 25 | Function @scheme[queue] creates a Banker's Queue with the given inputs. 26 | 27 | @examples[#:eval evaluate 28 | 29 | (queue 1 2 3 4 5 6) 30 | ] 31 | 32 | In the above example, the queue obtained will have 1 as its head element. 33 | } 34 | 35 | @defproc[(empty [t A]) (Queue Nothing)]{ 36 | An empty queue instantiated to type t. 37 | @examples[#:eval evaluate 38 | (empty Nothing) 39 | (empty Integer) 40 | ]} 41 | 42 | @defproc[(empty? [que (Queue A)]) Boolean]{ 43 | Function @scheme[empty?] checks if the given queue is empty or not. 44 | 45 | @examples[#:eval evaluate 46 | (empty? (queue 1 2 3 4 5 6)) 47 | (empty? (empty Integer)) 48 | ]} 49 | 50 | 51 | @defproc[(enqueue [a A] [que (Queue A)]) (Queue A)]{ 52 | Function @scheme[enqueue] takes an element and a queue and adds the given 53 | element into the @scheme[queue]. 54 | @examples[#:eval evaluate 55 | 56 | (enqueue 10 (queue 4 5 6)) 57 | ] 58 | 59 | In the above example, @scheme[(enqueue 10 (queue 4 5 6))] enqueues 10 to the 60 | end of the queue and returns @scheme[(queue 4 5 6 10)]. 61 | } 62 | 63 | @defproc[(head [que (Queue A)]) A]{ 64 | Function @scheme[head] takes a @scheme[queue] and returns the first element 65 | in the queue if its a non empty queue else throws an error. 66 | @examples[#:eval evaluate 67 | 68 | (head (queue 10 4 3 12)) 69 | 70 | (head (empty Integer)) 71 | ]} 72 | 73 | 74 | @defproc[(tail [que (Queue A)]) (Queue A)]{ 75 | Function @scheme[tail] takes a queue and returns the same queue 76 | without the first element. If the queue is empty it throws an error. 77 | 78 | @examples[#:eval evaluate 79 | 80 | (tail (queue 4 5 6)) 81 | 82 | (tail (empty Integer)) 83 | ] 84 | 85 | In the above example, @scheme[(tail (queue 4 5 6))], returns 86 | @scheme[(queue 5 6)]. 87 | } 88 | 89 | @defproc[(queue->list [que (Queue A)]) (Queue A)]{ 90 | Function @scheme[queue->list] takes a queue and returns a list of 91 | elements. The list will have head of the given queue as its first element. 92 | 93 | @examples[#:eval evaluate 94 | 95 | (queue->list (queue 10 2 34 4 15 6)) 96 | (queue->list (empty Integer)) 97 | ]} 98 | 99 | 100 | @defproc[(map [func (A B ... B -> C)] 101 | [que1 (Queue A)] 102 | [que2 (Queue B)] ...) (Queue A)]{ 103 | Function @scheme[map] is similar to @|racket-map| for lists. 104 | @examples[#:eval evaluate 105 | 106 | (queue->list (map add1 (queue 1 2 3 4 5 6))) 107 | 108 | (queue->list (map * (queue 1 2 3 4 5 6) (queue 1 2 3 4 5 6))) 109 | ]} 110 | 111 | @defproc[(fold [func (C A B ... B -> C)] 112 | [init C] 113 | [que1 (Queue A)] 114 | [que2 (Queue B)] ...) C]{ 115 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 116 | @margin-note{@scheme[fold] currently does not produce correct results when the 117 | given function is non-commutative.} 118 | 119 | @examples[#:eval evaluate 120 | 121 | (fold + 0 (queue 1 2 3 4 5 6)) 122 | 123 | (fold * 1 (queue 1 2 3 4 5 6) (queue 1 2 3 4 5 6)) 124 | ]} 125 | 126 | @defproc[(filter [func (A -> Boolean)] [que (Queue A)]) (Queue A)]{ 127 | Function @scheme[filter] is similar to @|racket-filter|. 128 | @examples[#:eval evaluate 129 | 130 | (define que (queue 1 2 3 4 5 6)) 131 | 132 | (queue->list (filter (λ: ([x : Integer]) (> x 5)) que)) 133 | 134 | (queue->list (filter (λ: ([x : Integer]) (< x 5)) que)) 135 | 136 | (queue->list (filter (λ: ([x : Integer]) (<= x 5)) que)) 137 | ]} 138 | 139 | @defproc[(remove [func (A -> Boolean)] [que (Queue A)]) (Queue A)]{ 140 | Function @scheme[remove] is similar to @|racket-filter| but 141 | @scheme[remove] removes the elements which match the predicate. 142 | @examples[#:eval evaluate 143 | 144 | (queue->list (remove (λ: ([x : Integer]) (> x 5)) 145 | (queue 1 2 3 4 5 6))) 146 | 147 | (queue->list (remove (λ: ([x : Integer]) (< x 5)) 148 | (queue 1 2 3 4 5 6))) 149 | 150 | (queue->list (remove (λ: ([x : Integer]) (<= x 5)) 151 | (queue 1 2 3 4 5 6))) 152 | ]} 153 | 154 | 155 | @defproc[(andmap [func (A B ... B -> Boolean)] 156 | [que1 (Queue A)] 157 | [que2 (Queue B)] ...) Boolean]{ 158 | Function @scheme[andmap] is similar to @|racket-andmap|. 159 | 160 | @examples[#:eval evaluate 161 | 162 | (andmap even? (queue 1 2 3 4 5 6)) 163 | 164 | (andmap odd? (queue 1 2 3 4 5 6)) 165 | 166 | (andmap positive? (queue 1 2 3 4 5 6)) 167 | 168 | (andmap negative? (queue -1 -2)) 169 | ]} 170 | 171 | 172 | @defproc[(ormap [func (A B ... B -> Boolean)] 173 | [que1 (Queue A)] 174 | [que2 (Queue B)] ...) Boolean]{ 175 | Function @scheme[ormap] is similar to @|racket-ormap|. 176 | 177 | @examples[#:eval evaluate 178 | 179 | (ormap even? (queue 1 2 3 4 5 6)) 180 | 181 | (ormap odd? (queue 1 2 3 4 5 6)) 182 | 183 | (ormap positive? (queue -1 -2 3 4 -5 6)) 184 | 185 | (ormap negative? (queue 1 -2)) 186 | ]} 187 | 188 | @defproc[(build-queue [size Natural] 189 | [func (Natural -> A)]) 190 | (Queue A)]{ 191 | Function @scheme[build-queue] is similar to @|racket-build-list|. 192 | @examples[#:eval evaluate 193 | 194 | (queue->list (build-queue 5 (λ:([x : Integer]) (add1 x)))) 195 | 196 | (queue->list (build-queue 5 (λ:([x : Integer]) (* x x)))) 197 | 198 | ]} 199 | 200 | @defproc[(head+tail [que (Queue A)]) 201 | (Pair A (Queue A))]{ 202 | Function @scheme[head+tail] returns a pair containing the head and the tail of 203 | the given queue. 204 | @examples[#:eval evaluate 205 | 206 | (head+tail (queue 1 2 3 4 5)) 207 | 208 | (head+tail (build-queue 5 (λ:([x : Integer]) (* x x)))) 209 | 210 | (head+tail (empty Integer)) 211 | 212 | ]} 213 | 214 | 215 | @(close-eval evaluate) 216 | -------------------------------------------------------------------------------- /pfds/scribblings/queues.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @title{Queues} 4 | Following queue structures implement and provide the functions 5 | empty?, enqueue, head, tail, queue and queue->list. All the queue 6 | structures are polymorphic. 7 | 8 | @local-table-of-contents[] 9 | @include-section{queue.scrbl} 10 | @include-section{physicists-queue.scrbl} 11 | @include-section{implicitqueue.scrbl} 12 | @include-section{bootstrapedqueue.scrbl} 13 | @include-section{realtimequeue.scrbl} 14 | @include-section{hood-melville-queue.scrbl} 15 | -------------------------------------------------------------------------------- /pfds/scribblings/randomaccesslist.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | @;(defmodule and have the type (RAList A) 3 | @;(require (for-label and have the type (RAList A). 4 | 5 | @title{Random Access Lists} 6 | 7 | Following Random Access List structures implement and provide the 8 | functions list, empty?, cons, head, tail, list-ref, list-set, drop, 9 | list-length and ->list. The implementations of the two data structures 10 | are based on numerical representations. Binary random access lists uses 11 | the binary number representation and running time of its basic list and 12 | random access operations, in worst-case, is logarithmic. Where as skew 13 | binary random access lists use skew binary number representation and 14 | running time of its basic operations is constant in worst-case. And both 15 | the implementations are polymorphic. And our benchmarks indicate that 16 | the operations of skew binary random access lists are faster. 17 | 18 | @local-table-of-contents[] 19 | @include-section{binaryrandomaccesslist.scrbl} 20 | @include-section{skewbinaryrandomaccesslist.scrbl} 21 | -------------------------------------------------------------------------------- /pfds/scribblings/realtimequeue.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/queue/real-time)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/queue/real-time)) 9 | 10 | @title[#:tag "rtq"]{Real-Time Queue} 11 | 12 | @defmodule[pfds/queue/real-time] 13 | 14 | Real-Time Queues eliminate the amortization by employing laziness and 15 | a technique called @italic{Scheduling}. The data structure gives a worst 16 | case running time of @bold{@italic{O(1)}} for the operations 17 | @scheme[head], @scheme[tail] and @scheme[enqueue]. 18 | 19 | @defform[(Queue A)]{A real-time queue of type @racket[A].} 20 | 21 | @defproc[(queue [a A] ...) (Queue A)]{ 22 | Function @scheme[queue] creates a Real-Time Queue with the 23 | given inputs. 24 | @examples[#:eval evaluate 25 | 26 | (queue 1 2 3 4 5 6) 27 | ] 28 | 29 | In the above example, the queue obtained will have 1 as its first element.} 30 | 31 | 32 | @defproc[(empty [t A]) (Queue A)]{ 33 | An empty queue. 34 | @examples[#:eval evaluate 35 | (empty Nothing) 36 | (empty Integer) 37 | ]} 38 | 39 | @defproc[(empty? [que (Queue A)]) Boolean]{ 40 | Function @scheme[empty?] checks if the given queue is empty or not. 41 | 42 | @examples[#:eval evaluate 43 | 44 | (empty? (queue 1 2 3 4 5 6)) 45 | 46 | (empty? (empty Integer)) 47 | 48 | ]} 49 | 50 | @defproc[(enqueue [a A] [que (Queue A)]) (Queue A)]{ 51 | Function@scheme[enqueue] takes an element and a queue and enqueues 52 | the given element into the queue. 53 | @examples[#:eval evaluate 54 | 55 | (enqueue 10 (queue 1 2 3 4 5 6)) 56 | ] 57 | 58 | In the above example, @scheme[(enqueue 10 que)] adds 10 to the end of 59 | @scheme[(queue 1 2 3 4 5 6)] and returns @scheme[(queue 1 2 3 4 5 6 10)].} 60 | 61 | @defproc[(head [que (Queue A)]) A]{ 62 | Function @scheme[head] takes a queue and gives the first element in the 63 | queue if queue is not empty else throws an error. 64 | @examples[#:eval evaluate 65 | 66 | (head (queue 1 2 3 4 5 6)) 67 | (head (empty Integer)) 68 | ]} 69 | 70 | @defproc[(tail [que (Queue A)]) (Queue A)]{ 71 | Function @scheme[tail] takes a queue and returns the same queue without 72 | head element of the given queue if its a non empty queue else throws an error. 73 | 74 | @examples[#:eval evaluate 75 | 76 | (tail (queue 1 2 3 4 5 6)) 77 | (tail (empty Integer)) 78 | ] 79 | 80 | In the above example, @scheme[(tail (queue 1 2 3 4 5 6))], returns 81 | @scheme[(queue 2 3 4 5 6)].} 82 | 83 | 84 | @defproc[(queue->list [que (Queue A)]) (Queue A)]{ 85 | Function @scheme[queue->list] takes a queue and returns a list of 86 | elements. The list will have head of the given queue as its first element. 87 | If the given queue is empty, then it returns an empty list. 88 | 89 | @examples[#:eval evaluate 90 | 91 | (queue->list (queue 10 2 34 4 15 6)) 92 | ]} 93 | 94 | @defproc[(map [func (A B ... B -> C)] 95 | [que1 (Queue A)] 96 | [que2 (Queue B)] ...) (Queue A)]{ 97 | Function @scheme[map] is similar to @|racket-map| for lists. 98 | @examples[#:eval evaluate 99 | 100 | (queue->list (map add1 (queue 1 2 3 4 5 6))) 101 | 102 | (queue->list (map * (queue 1 2 3 4 5 6) (queue 1 2 3 4 5 6))) 103 | ]} 104 | 105 | @defproc[(fold [func (C A B ... B -> C)] 106 | [init C] 107 | [que1 (Queue A)] 108 | [que2 (Queue B)] ...) C]{ 109 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 110 | @margin-note{@scheme[fold] currently does not produce correct results when the 111 | given function is non-commutative.} 112 | 113 | @examples[#:eval evaluate 114 | 115 | (fold + 0 (queue 1 2 3 4 5 6)) 116 | 117 | (fold * 1 (queue 1 2 3 4 5 6) (queue 1 2 3 4 5 6)) 118 | ]} 119 | 120 | @defproc[(filter [func (A -> Boolean)] [que (Queue A)]) (Queue A)]{ 121 | Function @scheme[filter] is similar to @|racket-filter|. 122 | @examples[#:eval evaluate 123 | 124 | (define que (queue 1 2 3 4 5 6)) 125 | 126 | (queue->list (filter (λ: ([x : Integer]) (> x 5)) que)) 127 | 128 | (queue->list (filter (λ: ([x : Integer]) (< x 5)) que)) 129 | 130 | (queue->list (filter (λ: ([x : Integer]) (<= x 5)) que)) 131 | ]} 132 | 133 | @defproc[(remove [func (A -> Boolean)] [que (Queue A)]) (Queue A)]{ 134 | Function @scheme[remove] is similar to @|racket-filter| but @scheme[remove] removes the elements which match the predicate. 135 | @examples[#:eval evaluate 136 | 137 | (queue->list (remove (λ: ([x : Integer]) (> x 5)) 138 | (queue 1 2 3 4 5 6))) 139 | 140 | (queue->list (remove (λ: ([x : Integer]) (< x 5)) 141 | (queue 1 2 3 4 5 6))) 142 | 143 | (queue->list (remove (λ: ([x : Integer]) (<= x 5)) 144 | (queue 1 2 3 4 5 6))) 145 | ]} 146 | 147 | 148 | @defproc[(andmap [func (A B ... B -> Boolean)] 149 | [que1 (Queue A)] 150 | [que2 (Queue B)] ...) Boolean]{ 151 | Function @scheme[andmap] is similar to @|racket-andmap|. 152 | 153 | @examples[#:eval evaluate 154 | 155 | (andmap even? (queue 1 2 3 4 5 6)) 156 | 157 | (andmap odd? (queue 1 2 3 4 5 6)) 158 | 159 | (andmap positive? (queue 1 2 3 4 5 6)) 160 | 161 | (andmap negative? (queue -1 -2)) 162 | ]} 163 | 164 | 165 | @defproc[(ormap [func (A B ... B -> Boolean)] 166 | [que1 (Queue A)] 167 | [que2 (Queue B)] ...) Boolean]{ 168 | Function @scheme[ormap] is similar to @|racket-ormap|. 169 | 170 | @examples[#:eval evaluate 171 | 172 | (ormap even? (queue 1 2 3 4 5 6)) 173 | 174 | (ormap odd? (queue 1 2 3 4 5 6)) 175 | 176 | (ormap positive? (queue -1 -2 3 4 -5 6)) 177 | 178 | (ormap negative? (queue 1 -2)) 179 | ]} 180 | 181 | @defproc[(build-queue [size Natural] 182 | [func (Natural -> A)]) 183 | (Queue A)]{ 184 | Function @scheme[build-queue] is similar to @|racket-build-list|. 185 | @examples[#:eval evaluate 186 | 187 | (queue->list (build-queue 5 (λ:([x : Integer]) (add1 x)))) 188 | 189 | (queue->list (build-queue 5 (λ:([x : Integer]) (* x x)))) 190 | 191 | ]} 192 | 193 | @defproc[(head+tail [que (Queue A)]) 194 | (Pair A (Queue A))]{ 195 | Function @scheme[head+tail] returns a pair containing the head and the tail of 196 | the given queue. 197 | @examples[#:eval evaluate 198 | 199 | (head+tail (queue 1 2 3 4 5)) 200 | 201 | (head+tail (build-queue 5 (λ:([x : Integer]) (* x x)))) 202 | 203 | (head+tail (empty Integer)) 204 | 205 | ]} 206 | 207 | 208 | @(close-eval evaluate) 209 | -------------------------------------------------------------------------------- /pfds/scribblings/redblacktrees.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/red-black-tree)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/red-black-tree)) 9 | 10 | @title{Red-Black Trees} 11 | 12 | @defmodule[pfds/red-black-tree] 13 | 14 | Red-Black Tree is a binary search tree in which every node is colored either 15 | red or black. The red black trees follow two balance invariants 16 | @itemlist{@item{No red node has a red child.}} 17 | @itemlist{@item{Every path from root to an empty node has the same 18 | number of black nodes.}} 19 | The above two invarients help in balancing the tree. 20 | All the operations @scheme[member?], @scheme[insert] 21 | and @scheme[delete] have worst case running 22 | time of @bold{@italic{O(log(n))}} 23 | 24 | 25 | @defform[(RedBlackTree A)]{A red-black tree of type @racket[A].} 26 | 27 | @defproc[(redblacktree [comp (A A -> Boolean)] [a A] ...) (RedBlackTree A)]{ 28 | Function @scheme[redblacktree] creates a Red-Black Tree with the 29 | given inputs. 30 | @examples[#:eval evaluate 31 | 32 | (redblacktree < 1 2 3 4 5) 33 | ] 34 | 35 | In the above example, the red black tree obtained will have 2 as its root 36 | and < as the comparison function.} 37 | 38 | @defproc[(empty? [rbt (RedBlackTree A)]) Boolean]{ 39 | Function @scheme[empty?] checks if the given red black tree is empty 40 | or not. 41 | @examples[#:eval evaluate 42 | 43 | (empty? (redblacktree < 1 2 3 4 5 6)) 44 | (empty? (redblacktree <)) 45 | ]} 46 | 47 | 48 | @defproc[(insert [a A] [rbt (RedBlackTree A)]) (RedBlackTree A)]{ 49 | Function @scheme[insert] takes an element and a red black tree and inserts 50 | the given element into the red black tree. 51 | @examples[#:eval evaluate 52 | 53 | (insert 10 (redblacktree < 1 2 3 4 5 6)) 54 | ] 55 | 56 | In the above example, insert adds the 10 to 57 | @scheme[(redblacktree < 1 2 3 4 5 6)].} 58 | 59 | 60 | @defproc[(root [rbt (RedBlackTree A)]) A]{ 61 | Function @scheme[root] takes a red black tree and returns the root of the 62 | given tree. 63 | @examples[#:eval evaluate 64 | 65 | (root (redblacktree < 1 2 3 4 5 6)) 66 | (root (redblacktree <)) 67 | ] 68 | 69 | In the above example, @scheme[(root (redblacktree < 1 2 3 4 5 6))], returns 2 70 | which is the root of @scheme[(redblacktree < 1 2 3 4 5 6)].} 71 | 72 | @defproc[(member? [rbt (RedBlackTree A)]) Boolean]{ 73 | Function @scheme[member?] takes an element and a red black tree and 74 | checks if the given element is a member of the tree or not. 75 | @examples[#:eval evaluate 76 | 77 | (member? 5 (redblacktree < 1 2 3 4 5 6)) 78 | (member? 10 (redblacktree < 1 2 3 4 5 6)) 79 | ]} 80 | 81 | @defproc[(delete-root [rbt (RedBlackTree A)]) (RedBlackTree A)]{ 82 | Function @scheme[delete-root] takes a red black tree and deletes the root 83 | element of the given tree. 84 | @examples[#:eval evaluate 85 | 86 | (delete-root (redblacktree < 1 2 3 4 5 6)) 87 | (delete-root (redblacktree <)) 88 | ] 89 | 90 | In the above example, @scheme[(delete-root rbtree)], delete the root of 91 | @scheme[(redblacktree < 1 2 3 4 5 6)] which happens to be 2 in this tree. } 92 | 93 | @defproc[(delete [elem A] [rbt (RedBlackTree A)]) (RedBlackTree A)]{ 94 | Function @scheme[delete] takes an element and red black tree and deletes 95 | the given element in the tree if the element is in the tree else throws 96 | an error. 97 | @examples[#:eval evaluate 98 | 99 | (delete 5 (redblacktree < 1 2 3 4 5 6)) 100 | 101 | (delete 10 (redblacktree < 1 2 3 4 5 6)) 102 | ] 103 | 104 | In the above example, @scheme[(delete 5 (redblacktree < 1 2 3 4 5 6))], 105 | deletes 5 in @scheme[(redblacktree < 1 2 3 4 5 6)].} 106 | 107 | 108 | @defproc[(redblacktree->list [rbt (RedBlackTree A)]) (Listof A)]{ 109 | Function @scheme[redblacktree->list] takes a red black tree and returns a 110 | list of all the elements in the given red black tree. 111 | 112 | @examples[#:eval evaluate 113 | 114 | (redblacktree->list (redblacktree > 1 2 3 4 5)) 115 | ]} 116 | 117 | 118 | @defproc[(map [comparer (C C -> Boolean)] 119 | [func (A B ... B -> C)] 120 | [rbt1 (RedBlackTree A)] 121 | [rbt2 (RedBlackTree B)] ...) (RedBlackTree A)]{ 122 | Function @scheme[map] is similar to @|racket-map| for lists. 123 | @examples[#:eval evaluate 124 | 125 | (redblacktree->list (map < add1 (redblacktree < 1 2 3 4 5 6))) 126 | 127 | (redblacktree->list (map < * (redblacktree < 1 2 3 4 5 6) 128 | (redblacktree < 1 2 3 4 5 6))) 129 | ]} 130 | 131 | @defproc[(fold [func (C A B ... B -> C)] 132 | [init C] 133 | [rbt1 (RedBlackTree A)] 134 | [rbt2 (RedBlackTree B)] ...) C]{ 135 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 136 | @margin-note{@scheme[fold] currently does not produce correct results when the 137 | given function is non-commutative.} 138 | 139 | @examples[#:eval evaluate 140 | 141 | (fold + 0 (redblacktree < 1 2 3 4 5 6)) 142 | 143 | (fold * 1 (redblacktree < 1 2 3 4 5 6) (redblacktree < 1 2 3 4 5 6)) 144 | ]} 145 | 146 | @defproc[(filter [func (A -> Boolean)] [rbt (RedBlackTree A)]) (RedBlackTree A)]{ 147 | Function @scheme[filter] is similar to @|racket-filter|. 148 | @examples[#:eval evaluate 149 | 150 | (define rbt (redblacktree < 1 2 3 4 5 6)) 151 | 152 | (redblacktree->list (filter (λ: ([x : Integer]) (> x 5)) rbt)) 153 | 154 | (redblacktree->list (filter (λ: ([x : Integer]) (< x 5)) rbt)) 155 | 156 | (redblacktree->list (filter (λ: ([x : Integer]) (<= x 5)) rbt)) 157 | ]} 158 | 159 | @defproc[(remove [func (A -> Boolean)] [rbt (RedBlackTree A)]) (RedBlackTree A)]{ 160 | Function @scheme[remove] is similar to @|racket-filter| but @scheme[remove] removes the elements which match the predicate. 161 | @examples[#:eval evaluate 162 | 163 | (redblacktree->list (remove (λ: ([x : Integer]) (> x 5)) 164 | (redblacktree < 1 2 3 4 5 6))) 165 | 166 | (redblacktree->list (remove (λ: ([x : Integer]) (< x 5)) 167 | (redblacktree < 1 2 3 4 5 6))) 168 | 169 | (redblacktree->list (remove (λ: ([x : Integer]) (<= x 5)) 170 | (redblacktree < 1 2 3 4 5 6))) 171 | ]} 172 | 173 | @(close-eval evaluate) 174 | -------------------------------------------------------------------------------- /pfds/scribblings/skewbinomialheap.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/heap/skew-binomial)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/heap/skew-binomial)) 9 | 10 | @title[#:tag "skewbh"]{Skew Binomial Heap} 11 | 12 | @defmodule[pfds/heap/skew-binomial] 13 | 14 | Skew Binomial Heaps are Binomial Heaps with hybrid numerical representation 15 | for heaps based on both skew binary numbers. Skew binary number representation 16 | is used since incrementing a skew binary number is quick and simple. Provides 17 | worst case running time of @bold{@italic{O(log(n))}} for the operations 18 | @scheme[find-min/max], @scheme[delete-min/max] and @scheme[merge]. 19 | And worst case running time of 20 | @bold{@italic{O(1)}} for the @scheme[insert] operation. 21 | 22 | @defform[(Heap A)]{A skew binomial heap of type @racket[A].} 23 | 24 | @defproc[(heap [comp (A A -> Boolean)] [a A] ...) (Heap A)]{ 25 | Function @scheme[heap] creates a Skew Binomial Heap with the given 26 | inputs. 27 | @examples[#:eval evaluate 28 | 29 | (heap < 1 2 3 4 5 6) 30 | ] 31 | 32 | In the above example, the binomial heap obtained will have elements 1 thru' 6 33 | with < as the comparison function.} 34 | 35 | 36 | @defproc[(empty? [heap (Heap A)]) Boolean]{ 37 | Function @scheme[empty?] checks if the given binomial heap is empty or not. 38 | 39 | @examples[#:eval evaluate 40 | 41 | (empty? (heap < 1 2 3 4 5 6)) 42 | 43 | (empty? (heap <)) 44 | ]} 45 | 46 | 47 | @defproc[(insert [a A] [heap (Heap A)] ...) (Heap A)]{ 48 | Function @scheme[insert] takes an element and a binomial heap and inserts 49 | the given element into the binomial heap. 50 | @examples[#:eval evaluate 51 | 52 | (insert 10 (heap < 1 2 3 4 5 6)) 53 | ] 54 | 55 | In the above example, insert adds the element 10 to 56 | @scheme[(heap < 1 2 3 4 5 6)].} 57 | 58 | @defproc[(find-min/max [heap (Heap A)]) A]{ 59 | Function @scheme[find-min/max] takes a binomial heap and gives the 60 | largest or the smallest element in the heap if binomial heap is not empty 61 | else throws an error. The element returned is max or min depends on the 62 | comparison function of the heap. 63 | @examples[#:eval evaluate 64 | 65 | (find-min/max (heap < 1 2 3 4 5 6)) 66 | (find-min/max (heap > 1 2 3 4 5 6)) 67 | (find-min/max (heap <)) 68 | ]} 69 | 70 | @defproc[(delete-min/max [heap (Heap A)]) (Heap A)]{ 71 | Function @scheme[delete-min/max] takes a binomial heap and returns the 72 | same heap with out the min or max element in the given heap. The element 73 | removed from the heap is max or min depends on the comparison function of the 74 | heap. 75 | @examples[#:eval evaluate 76 | 77 | (delete-min/max (heap < 1 2 3 4 5 6)) 78 | (delete-min/max (heap > 1 2 3 4 5 6)) 79 | (delete-min/max (heap <)) 80 | ] 81 | 82 | In the above example, @scheme[(delete-min/max (heap < 1 2 3 4 5 6))] 83 | deletes 1 and returns @scheme[(delete-min/max (heap < 2 3 4 5 6))]. 84 | And @scheme[(delete-min/max (heap > 1 2 3 4 5 6))] 85 | deletes 6 and returns @scheme[(delete-min/max (heap < 1 2 3 4 5))].} 86 | 87 | @defproc[(merge [bheap1 (Heap A)] [bheap2 (Heap A)]) (Heap A)]{ 88 | Function @scheme[merge] takes two binomial heaps and returns a 89 | merged binomial heap. Uses the comparison function in the first heap for 90 | merging and the same function becomes the comparison function for the 91 | merged heap. 92 | 93 | @margin-note{If the comparison 94 | functions do not have the same properties, merged heap might lose its 95 | heap-order.} 96 | 97 | @examples[#:eval evaluate 98 | 99 | (define bheap1 (heap < 1 2 3 4 5 6)) 100 | (define bheap2 (heap (λ: ([a : Integer] 101 | [b : Integer]) 102 | (< a b)) 103 | 10 20 30 40 50 60)) 104 | (merge bheap1 bheap2) 105 | 106 | ] 107 | 108 | In the above example, @scheme[(merge bheap1 bheap2)], merges the heaps and 109 | < will become the comparison function for the merged heap.} 110 | 111 | 112 | @defproc[(sorted-list [heap (Heap A)]) (Listof A)]{ 113 | Function @scheme[sorted-list] takes a binomial heap and returns a list 114 | which is sorted according to the comparison function of the heap. 115 | @examples[#:eval evaluate 116 | 117 | (sorted-list (heap > 1 2 3 4 5 6)) 118 | 119 | (sorted-list (heap < 1 2 3 4 5 6)) 120 | ]} 121 | 122 | 123 | @defproc[(map [comparer (C C -> Boolean)] 124 | [func (A B ... B -> C)] 125 | [hep1 (Heap A)] 126 | [hep2 (Heap B)] ...) (Heap A)]{ 127 | Function @scheme[map] is similar to @|racket-map| for lists. 128 | @examples[#:eval evaluate 129 | 130 | (sorted-list (map < add1 (heap < 1 2 3 4 5 6))) 131 | 132 | (sorted-list (map < * (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6))) 133 | ]} 134 | 135 | @defproc[(fold [func (C A B ... B -> C)] 136 | [init C] 137 | [hep1 (Heap A)] 138 | [hep2 (Heap B)] ...) C]{ 139 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 140 | @margin-note{@scheme[fold] currently does not produce correct results when the 141 | given function is non-commutative.} 142 | 143 | @examples[#:eval evaluate 144 | 145 | (fold + 0 (heap < 1 2 3 4 5 6)) 146 | 147 | (fold * 1 (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6)) 148 | ]} 149 | 150 | @defproc[(filter [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 151 | Function @scheme[filter] is similar to @|racket-filter|. 152 | @examples[#:eval evaluate 153 | 154 | (define hep (heap < 1 2 3 4 5 6)) 155 | 156 | (sorted-list (filter (λ: ([x : Integer]) (> x 5)) hep)) 157 | 158 | (sorted-list (filter (λ: ([x : Integer]) (< x 5)) hep)) 159 | 160 | (sorted-list (filter (λ: ([x : Integer]) (<= x 5)) hep)) 161 | ]} 162 | 163 | @defproc[(remove [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 164 | Function @scheme[remove] is similar to @|racket-filter| but @scheme[remove] removes the elements which match the predicate. 165 | @examples[#:eval evaluate 166 | 167 | (sorted-list (remove (λ: ([x : Integer]) (> x 5)) 168 | (heap < 1 2 3 4 5 6))) 169 | 170 | (sorted-list (remove (λ: ([x : Integer]) (< x 5)) 171 | (heap < 1 2 3 4 5 6))) 172 | 173 | (sorted-list (remove (λ: ([x : Integer]) (<= x 5)) 174 | (heap < 1 2 3 4 5 6))) 175 | ]} 176 | 177 | @defproc[(andmap [func (A B ... B -> Boolean)] 178 | [heap1 (Heap A)] 179 | [heap2 (Heap B)] ...) Boolean]{ 180 | Function @scheme[andmap] is similar to @|racket-andmap|. 181 | 182 | @examples[#:eval evaluate 183 | 184 | (andmap even? (heap < 1 2 3 4 5 6)) 185 | 186 | (andmap odd? (heap < 1 2 3 4 5 6)) 187 | 188 | (andmap positive? (heap < 1 2 3 4 5 6)) 189 | 190 | (andmap negative? (heap < -1 -2)) 191 | ]} 192 | 193 | 194 | @defproc[(ormap [func (A B ... B -> Boolean)] 195 | [heap1 (Heap A)] 196 | [heap2 (Heap B)] ...) Boolean]{ 197 | Function @scheme[ormap] is similar to @|racket-ormap|. 198 | 199 | @examples[#:eval evaluate 200 | 201 | (ormap even? (heap < 1 2 3 4 5 6)) 202 | 203 | (ormap odd? (heap < 1 2 3 4 5 6)) 204 | 205 | (ormap positive? (heap < -1 -2 3 4 -5 6)) 206 | 207 | (ormap negative? (heap < 1 -2)) 208 | ]} 209 | 210 | @defproc[(build-heap [size Natural] 211 | [func (Natural -> A)] 212 | [comp (A A -> Boolean)]) 213 | (Heap A)]{ 214 | Function @scheme[build-heap] is similar to @|racket-build-list| but this 215 | function takes an extra comparison function. 216 | 217 | @examples[#:eval evaluate 218 | 219 | (sorted-list (build-heap 5 (λ:([x : Integer]) (add1 x)) <)) 220 | 221 | (sorted-list (build-heap 5 (λ:([x : Integer]) (* x x)) <)) 222 | 223 | ]} 224 | 225 | @(close-eval evaluate) 226 | -------------------------------------------------------------------------------- /pfds/scribblings/splayheap.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/heap/splay)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/heap/splay)) 9 | 10 | @title{Splay Heap} 11 | 12 | @defmodule[pfds/heap/splay] 13 | 14 | Splay Heaps are very similar to balanced binary search trees. The difference 15 | between the two lies in the fact that Splay Heaps do not maintain any 16 | explicit balance information. Instead every operation restructures the 17 | tree with some simple transformations that increase the balance of the 18 | tree. Because of the restructuring on every operation, the worst case 19 | running time of all the operations is @bold{@italic{O(n)}}. But it can 20 | be easily shown that the amortized running time of is 21 | @bold{@italic{O(log(n))}} for the all the main operations 22 | @scheme[insert], @scheme[find-min/max], @scheme[delete-min/max] 23 | and @scheme[merge]. 24 | 25 | @defform[(Heap A)]{A splay heap of type @racket[A].} 26 | 27 | @defproc[(heap [comp (A A -> Boolean)] [a A] ...) (Heap A)]{ 28 | Function @scheme[heap] creates a Splay Heap with the given 29 | inputs. 30 | @examples[#:eval evaluate 31 | 32 | (heap < 1 2 3 4 5 6) 33 | ] 34 | 35 | In the above example, the splay heap obtained will have elements 1 thru' 6 36 | with < as the comparison function.} 37 | 38 | 39 | @defproc[(empty? [heap (Heap A)]) Boolean]{ 40 | Function @scheme[empty?] checks if the given splay heap is empty or not. 41 | 42 | @examples[#:eval evaluate 43 | 44 | (empty? (heap < 1 2 3 4 5 6)) 45 | 46 | (empty? (heap <)) 47 | ]} 48 | 49 | @defproc[(insert [a A] [heap (Heap A)] ...) (Heap A)]{ 50 | Function @scheme[insert] takes an element and a splay heap and inserts 51 | the given element into the splay heap. 52 | @examples[#:eval evaluate 53 | 54 | (insert 10 (heap < 1 2 3 4 5 6)) 55 | 56 | ] 57 | 58 | In the above example, @scheme[(insert 10 (heap < 1 2 3 4 5 6))] adds 10 59 | to the heap @scheme[(heap < 1 2 3 4 5 6)].} 60 | 61 | @defproc[(find-min/max [heap (Heap A)]) A]{ 62 | Function @scheme[find-min/max] takes a splay heap and gives the 63 | largest or the smallest element in the heap if splay heap is not empty 64 | else throws an error. The element returned is max or min depends on the 65 | comparison function of the heap. 66 | @examples[#:eval evaluate 67 | 68 | (find-min/max (heap < 1 2 3 4 5 6)) 69 | (find-min/max (heap > 1 2 3 4 5 6)) 70 | (find-min/max (heap <)) 71 | ]} 72 | 73 | @defproc[(delete-min/max [heap (Heap A)]) (Heap A)]{ 74 | Function @scheme[delete-min/max] takes a splay heap and returns the 75 | same heap with out the min or max element in the given heap. The element 76 | removed from the heap is max or min depends on the comparison function of the 77 | heap. 78 | @examples[#:eval evaluate 79 | 80 | (delete-min/max (heap < 1 2 3 4 5 6)) 81 | (delete-min/max (heap > 1 2 3 4 5 6)) 82 | (delete-min/max (heap >)) 83 | ] 84 | 85 | In the above example, @scheme[(delete-min/max (heap < 1 2 3 4 5 6))] 86 | deletes the smallest element 1. 87 | And @scheme[(delete-min/max (heap > 1 2 3 4 5 6))] deletes the largest 88 | element 6.} 89 | 90 | @defproc[(merge [sheap1 (Heap A)] [sheap2 (Heap A)]) (Heap A)]{ 91 | Function @scheme[merge] takes two splay heaps and returns a 92 | merged splay heap. Uses the comparison function in the first heap for 93 | merging and the same function becomes the comparison function for the 94 | merged heap. 95 | @margin-note{If the comparison 96 | functions do not have the same properties, merged heap might lose its 97 | heap-order.} 98 | @examples[#:eval evaluate 99 | 100 | (define sheap1 (heap < 1 2 3 4 5 6)) 101 | (define sheap2 (heap (λ: ([a : Integer] 102 | [b : Integer]) 103 | (< a b)) 104 | 10 20 30 40 50 60)) 105 | (merge sheap1 sheap2) 106 | 107 | ] 108 | 109 | In the above example, @scheme[(merge sheap1 sheap2)], merges the heaps and 110 | < will become the comparison function for the merged heap.} 111 | 112 | 113 | @defproc[(sorted-list [heap (Heap A)]) (Listof A)]{ 114 | Function @scheme[sorted-list] takes a splay heap and returns a list 115 | which is sorted according to the comparison function of the heap. 116 | @examples[#:eval evaluate 117 | 118 | (sorted-list (heap > 1 2 3 4 5 6)) 119 | (sorted-list (heap < 1 2 3 4 5 6)) 120 | (sorted-list (heap >)) 121 | ]} 122 | 123 | 124 | @defproc[(map [comparer (C C -> Boolean)] 125 | [func (A B ... B -> C)] 126 | [hep1 (Heap A)] 127 | [hep2 (Heap B)] ...) (Heap A)]{ 128 | Function @scheme[map] is similar to @|racket-map| for lists. 129 | @examples[#:eval evaluate 130 | 131 | (sorted-list (map < add1 (heap < 1 2 3 4 5 6))) 132 | 133 | (sorted-list (map < * (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6))) 134 | ]} 135 | 136 | @defproc[(fold [func (C A B ... B -> C)] 137 | [init C] 138 | [hep1 (Heap A)] 139 | [hep2 (Heap B)] ...) C]{ 140 | Function @scheme[fold] is similar to @|racket-foldl| or @|racket-foldr| 141 | @margin-note{@scheme[fold] currently does not produce correct results when the 142 | given function is non-commutative.} 143 | 144 | @examples[#:eval evaluate 145 | 146 | (fold + 0 (heap < 1 2 3 4 5 6)) 147 | 148 | (fold * 1 (heap < 1 2 3 4 5 6) (heap < 1 2 3 4 5 6)) 149 | ]} 150 | 151 | @defproc[(filter [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 152 | Function @scheme[filter] is similar to @|racket-filter|. 153 | @examples[#:eval evaluate 154 | 155 | (define hep (heap < 1 2 3 4 5 6)) 156 | 157 | (sorted-list (filter (λ: ([x : Integer]) (> x 5)) hep)) 158 | 159 | (sorted-list (filter (λ: ([x : Integer]) (< x 5)) hep)) 160 | 161 | (sorted-list (filter (λ: ([x : Integer]) (<= x 5)) hep)) 162 | ]} 163 | 164 | @defproc[(remove [func (A -> Boolean)] [hep (Heap A)]) (Heap A)]{ 165 | Function @scheme[remove] is similar to @|racket-filter| but @scheme[remove] removes the elements which match the predicate. 166 | @examples[#:eval evaluate 167 | 168 | (sorted-list (remove (λ: ([x : Integer]) (> x 5)) 169 | (heap < 1 2 3 4 5 6))) 170 | 171 | (sorted-list (remove (λ: ([x : Integer]) (< x 5)) 172 | (heap < 1 2 3 4 5 6))) 173 | 174 | (sorted-list (remove (λ: ([x : Integer]) (<= x 5)) 175 | (heap < 1 2 3 4 5 6))) 176 | ]} 177 | 178 | @defproc[(andmap [func (A B ... B -> Boolean)] 179 | [heap1 (Heap A)] 180 | [heap2 (Heap B)] ...) Boolean]{ 181 | Function @scheme[andmap] is similar to @|racket-andmap|. 182 | 183 | @examples[#:eval evaluate 184 | 185 | (andmap even? (heap < 1 2 3 4 5 6)) 186 | 187 | (andmap odd? (heap < 1 2 3 4 5 6)) 188 | 189 | (andmap positive? (heap < 1 2 3 4 5 6)) 190 | 191 | (andmap negative? (heap < -1 -2)) 192 | ]} 193 | 194 | 195 | @defproc[(ormap [func (A B ... B -> Boolean)] 196 | [heap1 (Heap A)] 197 | [heap2 (Heap B)] ...) Boolean]{ 198 | Function @scheme[ormap] is similar to @|racket-ormap|. 199 | 200 | @examples[#:eval evaluate 201 | 202 | (ormap even? (heap < 1 2 3 4 5 6)) 203 | 204 | (ormap odd? (heap < 1 2 3 4 5 6)) 205 | 206 | (ormap positive? (heap < -1 -2 3 4 -5 6)) 207 | 208 | (ormap negative? (heap < 1 -2)) 209 | ]} 210 | 211 | @defproc[(build-heap [size Natural] 212 | [func (Natural -> A)] 213 | [comp (A A -> Boolean)]) 214 | (Heap A)]{ 215 | Function @scheme[build-heap] is similar to @|racket-build-list| but this 216 | function takes an extra comparison function. 217 | 218 | @examples[#:eval evaluate 219 | 220 | (sorted-list (build-heap 5 (λ:([x : Integer]) (add1 x)) <)) 221 | 222 | (sorted-list (build-heap 5 (λ:([x : Integer]) (* x x)) <)) 223 | 224 | ]} 225 | 226 | @(close-eval evaluate) 227 | -------------------------------------------------------------------------------- /pfds/scribblings/streams.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/stream)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/stream)) 9 | 10 | @title[#:tag "streams"]{Streams} 11 | 12 | @defmodule[pfds/stream] 13 | 14 | Streams are nothing but lazy lists. They are similar to ordinary 15 | lists and they provide the same functionality as that of lists. The 16 | difference between Streams and lists is that they are lazy in nature and 17 | each cell of a Stream is suspended and is forced only when required. Streams 18 | have been used in some of the below mentioned data structures. Since 19 | each suspension comes with a little overhead, Streams should be used 20 | only when there is a good enough reason to do so. 21 | 22 | @defform[(Stream A)]{A stream of type @racket[A].} 23 | 24 | @defproc[(stream [a A] ...) (Stream A)]{ 25 | Function stream creates a Stream with the given inputs. 26 | 27 | @examples[#:eval evaluate 28 | 29 | (stream 1 2 3 4 5 6) 30 | ] 31 | 32 | In the above example, the stream obtained will be similar to lists but will 33 | lazy in nature. It will have 1 as its first element.} 34 | 35 | @defthing[empty-stream (Stream Nothing)]{ 36 | An empty stream.} 37 | 38 | @defproc[(empty-stream? [strm (Stream A)]) Boolean]{ 39 | Function @scheme[empty-stream?] takes a Stream checks if the given 40 | stream is empty. 41 | @examples[#:eval evaluate 42 | 43 | (empty-stream? (stream 1 2 3 4 5 6)) 44 | (empty-stream? empty-stream) 45 | 46 | ]} 47 | 48 | 49 | @defproc[(stream-cons [a A] [strm (Stream A)]) (Stream A)]{ 50 | Function @scheme[stream-cons] takes an element and a stream and adds 51 | the given element to the given stream. 52 | @examples[#:eval evaluate 53 | 54 | (stream-cons 10 (stream 1 2 3 4 5 6)) 55 | ] 56 | 57 | In the above example, @scheme[(stream-cons 10 (stream 1 2 3 4 5 6))] 58 | returns the stream @scheme[(stream 10 1 2 3 4 5 6)].} 59 | 60 | 61 | @defproc[(stream-car [strm (Stream A)]) A]{ 62 | Function @scheme[stream-car] takes a stream and returns the first element 63 | of the given stream. If the given stream is empty, then it throws an error. 64 | 65 | @examples[#:eval evaluate 66 | 67 | (stream-car (stream 1 2 3 4 5 6)) 68 | (stream-car empty-stream) 69 | ]} 70 | 71 | 72 | @defproc[(stream-cdr [strm (Stream A)]) (Stream A)]{ 73 | Function @scheme[stream-cdr] takes a stream and returns the same stream 74 | but without the first element of the given stream. 75 | @examples[#:eval evaluate 76 | 77 | (stream-cdr (stream 1 2 3 4 5 6)) 78 | (stream-cdr empty-stream) 79 | ] 80 | 81 | In the above example, @scheme[(stream-cdr strm)] returns 82 | @scheme[(stream 2 3 4 5 6)].} 83 | 84 | 85 | @defproc[(stream-append [strm1 (Stream A)] [strm2 (Stream A)]) (Stream A)]{ 86 | Function @scheme[stream-append] takes two streams and creates a new 87 | stream by appending the second stream to the end of first stream. 88 | 89 | @examples[#:eval evaluate 90 | 91 | (define strm1 (stream 1 2 3 4 5 6)) 92 | 93 | (define strm2 (stream 51 32 42)) 94 | 95 | (stream-append strm1 strm2) 96 | ] 97 | 98 | In the above example, @scheme[(stream-append strm1 strm2)] returns the stream, 99 | @scheme[(stream 1 2 3 4 5 6 51 32 42)].} 100 | 101 | 102 | @defproc[(stream-reverse [strm (Stream A)]) (Stream A)]{ 103 | Function @scheme[stream-reverse] takes a streams and gives a reversed 104 | stream back. 105 | @examples[#:eval evaluate 106 | 107 | (stream-reverse (stream 1 2 3 4 5 6)) 108 | ] 109 | 110 | In the above example, @scheme[(stream-reverse (stream 1 2 3 4 5 6))] returns 111 | @scheme[(stream 6 5 4 3 2 1)].} 112 | 113 | 114 | @defproc[(stream->list [strm (Stream A)]) (Listof A)]{ 115 | Function @scheme[stream->list] takes a stream and returns a list 116 | of elements which are in the same order as in the stream. 117 | @examples[#:eval evaluate 118 | 119 | (stream->list (stream 1 2 3 4 5 6)) 120 | (stream->list empty-stream) 121 | ]} 122 | 123 | 124 | @defproc[(drop [num Integer] [strm (Stream A)]) (Stream A)]{ 125 | Function @scheme[drop] takes an integer(say n) and a stream and creates a 126 | new stream which is same as the given stream but without the first n elements 127 | of the input stream. If the number of elements in the given stream is less 128 | than n, then @scheme[drop] throws an error. 129 | 130 | @examples[#:eval evaluate 131 | 132 | (drop 3 (stream 1 2 3 4 5 6)) 133 | (drop 10 (stream 1 2 3 4 5 6)) 134 | ] 135 | 136 | In the above example, @scheme[(drop 3 (stream 1 2 3 4 5 6))] returns 137 | @scheme[(stream 4 5 6)].} 138 | 139 | 140 | 141 | @defproc[(take [num Integer] [strm (Stream A)]) (Stream A)]{ 142 | Function @scheme[take] takes an integer(say n) and a stream and creates a 143 | new stream with the first n elements of the input stream. If the number of 144 | elements in the given stream is less than n, then @scheme[take] throws an 145 | error. 146 | @margin-note{@scheme[(take 5 (stream 1))] does not 147 | throw any error because of its lazy nature. @scheme[take] returns a suspension 148 | rather than finishing the whole computation.} 149 | @examples[#:eval evaluate 150 | 151 | (take 3 (stream 1 2 3 4 5 6)) 152 | (take 5 (stream 1)) 153 | ] 154 | 155 | In the above example, @scheme[(take 3 (stream 1 2 3 4 5 6))] returns 156 | @scheme[(stream 1 2 3)].} 157 | 158 | @(close-eval evaluate) 159 | -------------------------------------------------------------------------------- /pfds/scribblings/tries.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | 3 | @(require "helper.rkt") 4 | @(require (for-label pfds/trie)) 5 | 6 | @(define evaluate (make-base-eval)) 7 | @(evaluate '(require typed/racket)) 8 | @(evaluate '(require pfds/trie)) 9 | 10 | @title{Tries} 11 | 12 | @defmodule[pfds/trie] 13 | 14 | A Trie (also known as a Digital Search Tree) is a data structure 15 | which takes advantage of the structure of aggregate types to achieve 16 | good running times for its operations. Our implementation 17 | provides Tries in which the keys are lists of the element 18 | type; this is sufficient for representing many aggregate data 19 | structures. In our implementation, each trie is a multiway tree with each 20 | node of the multiway tree carrying data of base element type. Tries 21 | provide @racket[lookup] and @racket[insert] operations with better 22 | asymptotic running times than hash tables. This data structure is very 23 | useful when used for an aggregate type like strings. 24 | 25 | 26 | @defform[(Trie K V)]{A trie with keys of type @racket[K] and values of type 27 | @racket[V].} 28 | 29 | @defproc[(tries [values (Listof V)] [keys (Listof (Listof K))]) (Trie K V)]{ 30 | Function 31 | @scheme[tries] creates a trie with each value assigned to the list 32 | in keys at the corresponding location. 33 | @examples[#:eval evaluate 34 | 35 | (tries (list 1 2 3 4 5) 36 | (map string->list (list "abc" "xyz" "abcfg" "abxyz" "xyz12"))) 37 | ] 38 | 39 | In the above example, "abc" will have the value 1, "xyz" will get 2 40 | and so on.} 41 | 42 | 43 | @defproc[(trie [keys (Listof (Listof K))]) (Trie K Integer)]{ 44 | Function 45 | @scheme[trie] creates a trie by assigning a integer value to each list 46 | in keys. 47 | @examples[#:eval evaluate 48 | 49 | (trie (map string->list (list "abc" "xyz" "abcfg" "abxyz" "xyz12"))) 50 | ] 51 | 52 | In the above example, "abc" will have the value 1, "xyz" will get 2 53 | and so on.} 54 | 55 | 56 | @defproc[(insert [values (Listof V)] [keys (Listof (Listof K))] [trie (Trie K V)]) (Trie K V)]{ 57 | Inserts multiple keys into the trie. 58 | @examples[#:eval evaluate 59 | 60 | (insert (list 4 5) 61 | (map string->list (list "abcfg" "abxyz")) 62 | (tries (list 1 2) 63 | (map string->list (list "abc" "xyz")))) 64 | ] 65 | 66 | In the above example, "abcfg" will have the value 4, "abxyz" will get 5} 67 | 68 | 69 | @defproc[(bind [key (Listof K)] [value V] [trie (Trie K V)]) (Trie K V)]{ 70 | Inserts a key into the trie. 71 | @examples[#:eval evaluate 72 | 73 | (bind (string->list "abcfg") 3 74 | (tries (list 1 2) 75 | (map string->list (list "abc" "xyz")))) 76 | ]} 77 | 78 | 79 | 80 | @defproc[(lookup [key (Listof K)] [trie (Trie K V)]) V]{ 81 | Looks for the given key. If found, the value corresponding to the key is 82 | returned. Else throws an error. 83 | @examples[#:eval evaluate 84 | 85 | (lookup (string->list "abcde") 86 | (tries (list 1 2 3 4) 87 | (map string->list (list "123" "abc" "xyz" "abcde")))) 88 | 89 | (lookup (string->list "abc") 90 | (tries (list 1 2 3 4) 91 | (map string->list (list "123" "abc" "xyz" "abcde")))) 92 | 93 | (lookup (string->list "abcd") 94 | (tries (list 1 2 3 4) 95 | (map string->list (list "123" "abc" "xyz" "abcde")))) 96 | ]} 97 | @(close-eval evaluate) 98 | -------------------------------------------------------------------------------- /pfds/stream.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | (provide empty-stream? empty-stream stream-cons stream-car 4 | stream-cdr stream-append stream-reverse stream 5 | stream->list drop take Stream 6 | #;stream-map #;stream-foldl #;stream-foldr) 7 | 8 | (define-type (Stream A) (Rec Stream (U Null (Boxof (U (-> (Pair A Stream)) 9 | (Pair A Stream)))))) 10 | 11 | (define empty-stream null) 12 | 13 | (: empty-stream? : (All (A) ((Stream A) -> Boolean))) 14 | (define (empty-stream? stream) (null? stream)) 15 | 16 | 17 | (: stream-car : (All (A) ((Stream A) -> A))) 18 | (define (stream-car stream) 19 | (if (null? stream) 20 | (error 'stream-car "given stream is empty") 21 | (let ([p (unbox stream)]) 22 | (if (procedure? p) 23 | (let ([pair (p)]) 24 | (set-box! stream pair) 25 | (car pair)) 26 | (car p))))) 27 | 28 | (: stream-cdr : (All (A) ((Stream A) -> (Stream A)))) 29 | (define (stream-cdr stream) 30 | (if (null? stream) 31 | (error 'stream-cdr "given stream is empty") 32 | (let ([p (unbox stream)]) 33 | (if (procedure? p) 34 | (let ([pair (p)]) 35 | (set-box! stream pair) 36 | (cdr pair)) 37 | (cdr p))))) 38 | 39 | (define-syntax-rule (stream-cons x stream) 40 | (box (lambda () (cons x stream)))) 41 | 42 | (: stream-append : (All (A) (Stream A) (Stream A) -> (Stream A))) 43 | (define (stream-append stream1 stream2) 44 | (cond 45 | [(null? stream1) stream2] 46 | [(null? stream2) stream1] 47 | [else (stream-cons (stream-car stream1) 48 | (stream-append (stream-cdr stream1) stream2))])) 49 | 50 | (: stream-reverse : (All (A) (Stream A) -> (Stream A))) 51 | (define (stream-reverse stream) 52 | (: loop : (All (A) (Stream A) (Stream A) -> (Stream A))) 53 | (define (loop stream accum) 54 | (if (null? stream) 55 | accum 56 | (loop (stream-cdr stream) 57 | (ann (stream-cons (stream-car stream) accum) (Stream A))))) 58 | (loop stream empty-stream)) 59 | 60 | (: stream : (All (A) (A * -> (Stream A)))) 61 | (define (stream . xs) 62 | (: loop : (All (A) ((Listof A) -> (Stream A)))) 63 | (define (loop xs) 64 | (if (null? xs) 65 | '() 66 | (box (cons (car xs) (loop (cdr xs)))))) 67 | (loop xs)) 68 | 69 | (: stream->list : (All (A) ((Stream A) -> (Listof A)))) 70 | (define (stream->list stream) 71 | (if (null? stream) 72 | '() 73 | (cons (stream-car stream) (stream->list (stream-cdr stream))))) 74 | 75 | 76 | (: drop : (All (A) (Integer (Stream A) -> (Stream A)))) 77 | (define (drop num stream) 78 | (cond 79 | [(zero? num) stream] 80 | [(null? stream) (error 'drop "not enough elements to drop")] 81 | [else (let ([forced (unbox stream)]) 82 | (if (procedure? forced) 83 | (let ([pair (forced)]) 84 | (set-box! stream pair) 85 | (drop (sub1 num) (cdr pair))) 86 | (drop (sub1 num) (cdr forced))))])) 87 | 88 | 89 | (: take : (All (A) (Integer (Stream A) -> (Stream A)))) 90 | (define (take num stream) 91 | (cond 92 | [(zero? num) empty-stream] 93 | [(null? stream) (error 'take "not enough elements to take")] 94 | [else (let ([forced (unbox stream)]) 95 | (if (procedure? forced) 96 | (let ([pair (forced)]) 97 | (set-box! stream pair) 98 | (stream-cons (car pair) (take (sub1 num) (cdr pair)))) 99 | (stream-cons (car forced) (take (sub1 num) (cdr forced)))))])) 100 | 101 | 102 | 103 | 104 | ;(: stream-map : (All (A C B ...) ((A B ... B -> C) (Stream A) 105 | ; (Stream B) ... B -> 106 | ; (Stream C)))) 107 | ;(define (stream-map func strm . strms) 108 | ; (if (or (empty? strm) (ormap empty? strms)) 109 | ; empty 110 | ; (delay (make-InStream (apply func 111 | ; (stream-car strm) 112 | ; (map stream-car strms)) 113 | ; (apply stream-map 114 | ; func 115 | ; (stream-cdr strm) 116 | ; (map stream-cdr strms)))))) 117 | ; 118 | ;(: stream-foldl : 119 | ; (All (C A B ...) ((C A B ... B -> C) C (Stream A) 120 | ; (Stream B) ... B -> C))) 121 | ;(define (stream-foldl func base fst . rst) 122 | ; (if (or (empty? fst) (ormap empty? rst)) 123 | ; base 124 | ; (apply stream-foldl 125 | ; func 126 | ; (apply func base (stream-car fst) (map stream-car rst)) 127 | ; (stream-cdr fst) 128 | ; (map stream-cdr rst)))) 129 | ; 130 | ;(: stream-foldr : 131 | ; (All (C A B ...) ((C A B ... B -> C) C (Stream A) 132 | ; (Stream B) ... B -> C))) 133 | ;(define (stream-foldr func base fst . rst) 134 | ; (if (or (empty? fst) (ormap empty? rst)) 135 | ; base 136 | ; (apply func (apply stream-foldr 137 | ; func 138 | ; base 139 | ; (stream-cdr fst) 140 | ; (map stream-cdr rst)) 141 | ; (stream-car fst) 142 | ; (map stream-car rst)))) 143 | ; 144 | 145 | 146 | 147 | ;;(: stream-filter : (All (A) ((A -> Boolean) (Stream A) -> (Stream A)))) 148 | ;;(define (filter func strm) 149 | ;; (: inner : (All (A) ((A -> Boolean) (Stream A) (Stream A) -> (Stream A)))) 150 | ;; (define (inner func strm accum) 151 | ;; (if (empty? strm) 152 | ;; accum 153 | ;; (let ([head (head strm)] 154 | ;; [tail (tail strm)]) 155 | ;; (if (func head) 156 | ;; (inner func tail (stream-cons head accum)) 157 | ;; (inner func tail accum))))) 158 | ;; (inner func strm empty)) 159 | ;; 160 | ;; 161 | ;;(: stream-remove : (All (A) ((A -> Boolean) (Stream A) -> (Stream A)))) 162 | ;;(define (remove func strm) 163 | ;; (: inner : (All (A) ((A -> Boolean) (Stream A) (Stream A) -> (Stream A)))) 164 | ;; (define (inner func strm accum) 165 | ;; (if (empty? strm) 166 | ;; accum 167 | ;; (let ([head (head strm)] 168 | ;; [tail (tail strm)]) 169 | ;; (if (func head) 170 | ;; (inner func tail accum) 171 | ;; (inner func tail (stream-cons head accum)))))) 172 | ;; (inner func strm empty)) 173 | -------------------------------------------------------------------------------- /pfds/tests/bankers-deque-benchmarks.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | (require "../deque/bankers.rkt") 3 | 4 | ;; ######################### 5 | ;; Performance-related Tests 6 | ;; ######################### 7 | 8 | 9 | ;; Test to show performance improvement from less laziness 10 | ;; (ie using partial stream instead of stream) 11 | ;; ------------------------------------------------------- 12 | 13 | ;; enqueue in rear, pull from front 14 | (let ([q (time (build-deque (expt 2 21) add1))]) 15 | (time 16 | (let: loop : Integer ([q : (Deque Positive-Integer) q]) 17 | (if (empty? q) 0 (+ (head q) (loop (tail q))))))) 18 | ;; on Steve's desktop (i7-2600k, 16GB), from cmd line 19 | ;; (1st time is deque build, 2nd is summing deque elements) 20 | ;; with streams: 21 | ;cpu time: 1424 real time: 1428 gc time: 1132 22 | ;cpu time: 3612 real time: 3621 gc time: 2344 23 | ;; with partial streams: 24 | ;cpu time: 512 real time: 512 gc time: 340 25 | ;cpu time: 3580 real time: 3590 gc time: 2384 26 | 27 | 28 | ;; enqueue in rear, pull from rear 29 | (let ([q (time (build-deque (expt 2 21) add1))]) 30 | (time 31 | (let: loop : Integer ([q : (Deque Positive-Integer) q]) 32 | (if (empty? q) 0 (+ (last q) (loop (init q))))))) 33 | ;; on Steve's desktop (i7-2600k, 16GB), from cmd line 34 | ;; (1st time is deque build, 2nd is summing deque elements) 35 | ;; with streams: 36 | ;cpu time: 1544 real time: 1549 gc time: 1252 37 | ;cpu time: 2293 real time: 2302 gc time: 1393 38 | ;; with partial streams: 39 | ;cpu time: 536 real time: 538 gc time: 380 40 | ;cpu time: 2824 real time: 2832 gc time: 1892 41 | ;; build is faster but extra checks in partial stream results in slower dequeing 42 | 43 | ;; enqueue in front, pull from front 44 | (let ([q (time (build-deque-front (expt 2 21) add1))]) 45 | (time 46 | (let: loop : Integer ([q : (Deque Positive-Integer) q]) 47 | (if (empty? q) 0 (+ (head q) (loop (tail q))))))) 48 | ;; on Steve's desktop (i7-2600k, 16GB), from cmd line 49 | ;; (1st time is deque build, 2nd is summing deque elements) 50 | ;; with streams: 51 | ;cpu time: 1452 real time: 1455 gc time: 1204 52 | ;cpu time: 2264 real time: 2270 gc time: 1348 53 | ;; with partial streams: 54 | ;cpu time: 380 real time: 380 gc time: 216 55 | ;cpu time: 2621 real time: 2626 gc time: 1688 56 | ;; build is faster but extra checks in partial stream results in slower dequeing 57 | 58 | 59 | ;; enqueue in front, pull from rear 60 | (let ([q (time (build-deque-front (expt 2 21) add1))]) 61 | (time 62 | (let: loop : Integer ([q : (Deque Positive-Integer) q]) 63 | (if (empty? q) 0 (+ (last q) (loop (init q))))))) 64 | ;; on Steve's desktop (i7-2600k, 16GB), from cmd line 65 | ;; (1st time is deque build, 2nd is summing deque elements) 66 | ;; with streams: 67 | ;cpu time: 1444 real time: 1449 gc time: 1172 68 | ;cpu time: 3568 real time: 3580 gc time: 2368 69 | ;; with partial streams: 70 | ;cpu time: 384 real time: 384 gc time: 224 71 | ;cpu time: 3736 real time: 3748 gc time: 2524 72 | -------------------------------------------------------------------------------- /pfds/tests/bankers-deque-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | (require "../deque/bankers.rkt") 3 | (require typed/test-engine/scheme-tests) 4 | 5 | (check-expect (empty? (empty Nothing)) #t) 6 | (check-expect (empty? (deque 1 2 3)) #f) 7 | 8 | (check-expect (head (deque 1 2 3)) 1) 9 | (check-expect (head (deque 5 6 2 3)) 5) 10 | (check-error (head (empty Nothing)) "head: given deque is empty") 11 | 12 | (check-expect (last (deque 1 2 3)) 3) 13 | (check-expect (last (deque 5 6 2 8)) 8) 14 | (check-error (last (empty Nothing)) "last: given deque is empty") 15 | 16 | (check-expect (deque->list (tail (deque 1 2 3))) (list 2 3)) 17 | (check-expect (deque->list (tail (deque 1 2 3 5 7 8))) 18 | (list 2 3 5 7 8)) 19 | (check-error (tail (empty Nothing)) "tail: given deque is empty") 20 | 21 | (check-expect (deque->list (init (deque 1 2 3))) (list 1 2)) 22 | (check-expect (deque->list (init (deque 1 2 3 5 7 8))) 23 | (list 1 2 3 5 7)) 24 | (check-error (init (empty Nothing)) "init: given deque is empty") 25 | 26 | (check-expect (deque->list (enqueue 1 (empty Integer))) (list 1)) 27 | (check-expect (deque->list (enqueue 4 (deque 1 2))) (list 1 2 4)) 28 | 29 | (check-expect (deque->list (enqueue-front 1 (empty Integer))) (list 1)) 30 | (check-expect (deque->list (enqueue-front 4 (deque 1 2))) (list 4 1 2)) 31 | 32 | (define lst (build-list 100 (λ: ([x : Integer]) x))) 33 | 34 | (check-expect (deque->list 35 | (enqueue-front 40 (enqueue-front 4 (apply deque lst)))) 36 | (cons 40 (cons 4 lst))) 37 | 38 | (check-expect (deque->list (apply deque lst)) lst) 39 | 40 | (check-expect (deque->list (map + (deque 1 2 3 4 5) (deque 1 2 3 4 5))) 41 | (list 2 4 6 8 10)) 42 | 43 | (check-expect (deque->list (map - (deque 1 2 3 4 5) (deque 1 2 3 4 5))) 44 | (list 0 0 0 0 0)) 45 | 46 | (check-expect (foldl + 0 (deque 1 2 3 4 5)) 15) 47 | 48 | (check-expect (foldl - 2 (deque 1 2 3 4 5)) -13) 49 | 50 | (check-expect (foldr + 0 (deque 1 2 3 4 5)) 15) 51 | 52 | (check-expect (foldr + 0 (deque 1 2 3 4 5) (deque 1 2 3 4 5)) 30) 53 | 54 | (check-expect (deque->list (filter positive? (deque 1 2 -4 5 0 -6 12 3 -2))) 55 | (list 1 2 5 12 3)) 56 | 57 | (check-expect (deque->list (filter negative? (deque 1 2 -4 5 0 -6 12 3 -2))) 58 | (list -4 -6 -2)) 59 | 60 | (check-expect (deque->list (remove positive? (deque 1 2 -4 5 0 -6 12 3 -2))) 61 | (list -4 0 -6 -2)) 62 | 63 | (check-expect (deque->list (remove negative? (deque 1 2 -4 5 0 -6 12 3 -2))) 64 | (list 1 2 5 0 12 3)) 65 | 66 | 67 | (test) 68 | -------------------------------------------------------------------------------- /pfds/tests/bankers-queue-benchmarks.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | (require "../queue/bankers.rkt") 3 | 4 | ;; ######################### 5 | ;; Performance-related Tests 6 | ;; ######################### 7 | 8 | ;; Testing proper queue rotation (see issue #3 on github) 9 | ;; ------------------------------------------------------ 10 | ;; When doing a "rotation", ie reversing the rear list and appending that to 11 | ;; the end of the front list, the reverse operation should be delayed and only 12 | ;; forced when that section of the front list is needed. 13 | 14 | ;; To demonstrate, build a queue of size 2^n - 2. Taking the tail of this queue 15 | ;; triggers a rotation. In a proper implementation, the reversing is delayed 16 | ;; so the tail operation should be instantaneous (ie should take 0 time). 17 | 18 | ;; n = 21 19 | (let ([q (build-queue (assert (- (expt 2 21) 2) positive?) add1)]) 20 | (time (tail q))) 21 | 22 | ;; 2013-03-10, on Steve's desktop (i7-2600k, 16GB), in drracket 23 | ;; (I dont know why the gc time is so high, probably an anomaly, but the 24 | ;; important number is 0 after the fix) 25 | ;; before fix: cpu time: 468 real time: 469 gc time: 400 26 | ;; after fix: cpu time: 0 real time: 0 gc time: 0 27 | 28 | 29 | ;; Another way to expose premature rotation is to manipulate a queue into a 30 | ;; state such that the next tail operation forces the reversing thunk. If the 31 | ;; reversing was done prematurely, then taking the tail of this queue will be 32 | ;; instantaneous. But in a proper implementation, taking the tail should be an 33 | ;; expensive operation. 34 | 35 | ;; To get such a queue, build a queue of size 2^n - 2 and then drop the first 36 | ;; 2^(n-1) - 1 elements (ie, half). In a proper implementation, taking the tail 37 | ;; of this queue should be an expensive operation in a correct implementation. 38 | 39 | ;; n = 21, 2^21 - 2 = 2097150; 2^20 - 1 = 1048575 40 | (let* ([n 21] 41 | [thresh (sub1 (expt 2 (sub1 n)))]) 42 | (let loop ([q (build-queue (assert (- (expt 2 n) 2) positive?) add1)] 43 | [i 0]) 44 | (if (< i thresh) 45 | (loop (tail q) (add1 i)) 46 | (time (tail q))))) 47 | 48 | ;; 2013-03-10, on Steve's desktop (i7-2600k, 16GB), in drracket 49 | ;; before fix: cpu time: cpu time: 0 real time: 0 gc time: 0 50 | ;; after fix: cpu time: 56 real time: 60 gc time: 44 51 | 52 | 53 | 54 | ;; Testing queues used persistently (assumes fixed issue#3, described above) 55 | ;; --------------------------------------------------------------------------- 56 | ;; To maintain constant, amortized time operations when the queue is used 57 | ;; persistently, doing an expensive rotation should memoize the result so that 58 | ;; repeating the same expensive operation completes instantaneously. 59 | 60 | ;; This is the same as the second example above, except the "expensive" tail 61 | ;; is called twice. The second call should be instantaneous. 62 | (let* ([n 21] 63 | [thresh (sub1 (expt 2 (sub1 n)))]) 64 | (let loop ([q (build-queue (assert (- (expt 2 n) 2) positive?) add1)] 65 | [i 0]) 66 | (if (< i thresh) 67 | (loop (tail q) (add1 i)) 68 | (begin 69 | (time (tail q)) 70 | (time (tail q)))))) 71 | 72 | ;; 2013-03-10, on Steve's desktop (i7-2600k, 16GB), in drracket 73 | ;; after fix: 74 | ;; cpu time: 60 real time: 61 gc time: 48 75 | ;; cpu time: 0 real time: 0 gc time: 0 76 | 77 | 78 | ;; Test to show performance improvement from less laziness 79 | ;; (ie using partial stream instead of stream) 80 | ;; ------------------------------------------------------- 81 | 82 | (let ([q (time (build-queue (expt 2 21) add1))]) 83 | (time 84 | (let: loop : Integer ([q : (Queue Positive-Integer) q]) 85 | (if (empty? q) 0 (+ (head q) (loop (tail q))))))) 86 | 87 | ;; 2013-03-11, on Steve's desktop (i7-2600k, 16GB), from racket cmd line 88 | ;; before commit 98c2723e35326291fb6909c2217b3f7c4b89ce39 89 | ;; (1st time is queue build, 2nd is summing queue elements) 90 | ;cpu time: 1748 real time: 1752 gc time: 1464 91 | ;cpu time: 1776 real time: 1779 gc time: 1072 92 | ;; after: 93 | ;cpu time: 516 real time: 517 gc time: 336 94 | ;cpu time: 1468 real time: 1470 gc time: 852 95 | 96 | -------------------------------------------------------------------------------- /pfds/tests/bankers-queue-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | (require "../queue/bankers.rkt") 3 | (require typed/test-engine/scheme-tests) 4 | 5 | (check-expect (empty? (empty Integer)) #t) 6 | (check-expect (empty? (queue 1)) #f) 7 | (check-expect (empty? (queue 1 2)) #f) 8 | 9 | (check-expect (head (queue 4 5 2 3)) 4) 10 | (check-expect (head (queue 2)) 2) 11 | 12 | (check-expect (queue->list (tail (queue 4 5 2 3))) 13 | (list 5 2 3)) 14 | (check-expect (queue->list (tail (queue 1))) null) 15 | (check-error (tail (empty Integer)) "tail: given queue is empty") 16 | 17 | (check-expect (queue->list (enqueue 1 (empty Integer))) 18 | (list 1)) 19 | (check-expect (queue->list (enqueue 1 (queue 1 2 3))) (list 1 2 3 1)) 20 | 21 | (check-expect (head (enqueue 1 (empty Integer))) 1) 22 | (check-expect (head (enqueue 10 (queue 5 2 3))) 5) 23 | 24 | (check-error (head (empty Integer)) "head: given queue is empty") 25 | 26 | (check-expect (queue->list (map + (queue 1 2 3 4 5) (queue 1 2 3 4 5))) 27 | (list 2 4 6 8 10)) 28 | 29 | (check-expect (queue->list (map - (queue 1 2 3 4 5) (queue 1 2 3 4 5))) 30 | (list 0 0 0 0 0)) 31 | 32 | (check-expect (fold + 0 (queue 1 2 3 4 5)) 15) 33 | 34 | (check-expect (fold + 0 (queue 1 2 3 4 5) (queue 1 2 3 4 5)) 30) 35 | 36 | (check-expect (queue->list (filter positive? (queue 1 2 -4 5 0 -6 12 3 -2))) 37 | (list 1 2 5 12 3)) 38 | 39 | (check-expect (queue->list (filter negative? (queue 1 2 -4 5 0 -6 12 3 -2))) 40 | (list -4 -6 -2)) 41 | 42 | (check-expect (queue->list (remove positive? (queue 1 2 -4 5 0 -6 12 3 -2))) 43 | (list -4 0 -6 -2)) 44 | 45 | (check-expect (queue->list (remove negative? (queue 1 2 -4 5 0 -6 12 3 -2))) 46 | (list 1 2 5 0 12 3)) 47 | 48 | (test) -------------------------------------------------------------------------------- /pfds/tests/binary-ran-access-list-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/scheme 2 | (require (prefix-in rk: racket/base)) 3 | (require pfds/ralist/binary) 4 | (require typed/test-engine/scheme-tests) 5 | 6 | (check-expect (head (list 1 2 3 4 5 6 7)) 1) 7 | (check-expect (head (list "" "")) "") 8 | (check-expect (tail (list 1)) (list)) 9 | (check-expect (head (tail (list 1 2 3 4 5 6 7))) 2) 10 | 11 | (check-expect (empty? (tail (list 1))) #t) 12 | (check-expect (empty? (tail (list 2 1))) #f) 13 | 14 | (check-expect (->list (tail (list 1 2 3 4 5 6 7))) 15 | (rk:list 2 3 4 5 6 7)) 16 | 17 | (check-expect (->list (tail (tail (list 1 2 3 4 5 6 7)))) 18 | (rk:list 3 4 5 6 7)) 19 | 20 | (check-expect (drop 1 (list 1)) (list)) 21 | (check-expect (->list (drop 2 (list 1 2 3 4 5 6 7))) 22 | (rk:list 3 4 5 6 7)) 23 | 24 | (check-expect (->list (drop 0 (list 1 2 3 4 5 6 7))) 25 | (rk:list 1 2 3 4 5 6 7)) 26 | (check-error (drop 8 (list 1 2 3 4 5 6 7)) 27 | "drop: not enough elements to drop") 28 | (check-error (drop -1 (list 1 2 3 4 5 6 7)) 29 | "drop: not enough elements to drop") 30 | 31 | (check-expect (->list (list-set (list 1 2 3 4 5 6 7) 2 1234)) 32 | (rk:list 1 2 1234 4 5 6 7)) 33 | 34 | (check-expect (->list (list-set (list 1 2 3 4 5 6 7) 0 1234)) 35 | (rk:list 1234 2 3 4 5 6 7)) 36 | 37 | (check-error (list-set (list 1 2 3 4 5 6 7) -2 1234) 38 | "list-set: given index out of bound") 39 | 40 | (check-error (list-set (list 1 2 3 4 5 6 7) 20 1234) 41 | "list-set: given index out of bound") 42 | 43 | (define lst (rk:build-list 100 (λ(x) x))) 44 | (check-expect (->list (apply list lst)) lst) 45 | 46 | (check-expect (length empty) 0) 47 | (check-expect (length (list 1)) 1) 48 | (check-expect (length (list 1 2 3 4 5 6 7)) 7) 49 | 50 | (check-expect (length (list 1 2 3 4 5)) 5) 51 | 52 | (check-expect (length (apply list lst)) 100) 53 | 54 | (check-expect (->list (map + (list 1 2 3 4 5) (list 1 2 3 4 5))) 55 | (rk:list 2 4 6 8 10)) 56 | 57 | (check-expect (->list (map - (list 1 2 3 4 5) (list 1 2 3 4 5))) 58 | (rk:list 0 0 0 0 0)) 59 | 60 | (check-expect (foldl + 0 (list 1 2 3 4 5)) 15) 61 | 62 | (check-expect (foldl - 2 (list 1 2 3 4 5)) -13) 63 | 64 | (check-expect (foldr + 0 (list 1 2 3 4 5)) 15) 65 | 66 | (check-expect (foldr + 0 (list 1 2 3 4 5) (list 1 2 3 4 5)) 30) 67 | 68 | (check-expect (->list (filter positive? (list 1 2 -4 5 0 -6 12 3 -2))) 69 | (rk:list 1 2 5 12 3)) 70 | 71 | (check-expect (->list (filter negative? (list 1 2 -4 5 0 -6 12 3 -2))) 72 | (rk:list -4 -6 -2)) 73 | 74 | (check-expect (->list (remove positive? (list 1 2 -4 5 0 -6 12 3 -2))) 75 | (rk:list -4 0 -6 -2)) 76 | 77 | (check-expect (->list (remove negative? (list 1 2 -4 5 0 -6 12 3 -2))) 78 | (rk:list 1 2 5 0 12 3)) 79 | (test) 80 | -------------------------------------------------------------------------------- /pfds/tests/binomialheap-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require pfds/heap/binomial) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | 6 | (: less-than? : (Integer Integer -> Boolean)) 7 | (define (less-than? a b) 8 | (<= a b)) 9 | 10 | (: gt : (Integer Integer -> Boolean)) 11 | (define (gt a b) 12 | (> a b)) 13 | 14 | (: str-less-than? : (String String -> Boolean)) 15 | (define (str-less-than? a b) 16 | (string<=? a b)) 17 | 18 | (check-expect (find-min/max (heap less-than? 1 2 3 4)) 1) 19 | (check-expect (find-min/max (heap less-than? 1 2 3 0)) 0) 20 | (check-expect (find-min/max (heap less-than? 1 2 -3 4)) -3) 21 | (check-error (find-min/max (delete-min/max (heap less-than? 1))) 22 | "find-min/max: given heap is empty") 23 | 24 | (check-expect (sorted-list (delete-min/max 25 | (heap less-than? 1 2 3 4))) 26 | (list 2 3 4)) 27 | (check-expect (sorted-list (delete-min/max 28 | (heap less-than? 1 2 3 0))) 29 | (list 1 2 3)) 30 | (check-expect (sorted-list (delete-min/max 31 | (heap less-than? 1 2 -3 4))) 32 | (list 1 2 4)) 33 | (check-error (delete-min/max (delete-min/max (heap less-than? 1))) 34 | "delete-min/max: given heap is empty") 35 | 36 | (check-expect (sorted-list (delete-min/max 37 | (heap less-than? 1))) (list)) 38 | (check-expect (sorted-list (delete-min/max 39 | (heap less-than? 1 -2 -3 -4))) 40 | (list -3 -2 1)) 41 | 42 | (check-expect (sorted-list (insert 10 (ann (heap less-than? 1 -2 -3 -4) 43 | (Heap Integer)))) 44 | (list -4 -3 -2 1 10)) 45 | 46 | (check-expect (sorted-list (insert -10 (heap less-than? 1 20 -3 -4))) 47 | (list -10 -4 -3 1 20)) 48 | 49 | (check-expect (sorted-list (insert 5 (heap less-than? 1 2 -3 -4))) 50 | (list -4 -3 1 2 5)) 51 | 52 | (check-expect (sorted-list (merge (ann (heap less-than? 2 3 -10) 53 | (Heap Integer)) 54 | (ann (heap less-than? 1 -2 -3 -4) 55 | (Heap Integer)))) 56 | (list -10 -4 -3 -2 1 2 3)) 57 | 58 | (check-expect (sorted-list (merge (delete-min/max 59 | (ann (heap less-than? -1 5) 60 | (Heap Integer))) 61 | (ann (heap less-than? 1 -2 -3 -4) 62 | (Heap Integer)))) 63 | (list -4 -3 -2 1 5)) 64 | 65 | (check-expect (sorted-list (merge (heap less-than? 1 -2 -3 -4) 66 | (delete-min/max 67 | (heap less-than? -1 1)))) 68 | (list -4 -3 -2 1 1)) 69 | 70 | (define int-list (build-list 100 (λ: ([x : Integer]) x))) 71 | 72 | (check-expect (sorted-list (apply heap < int-list)) 73 | int-list) 74 | 75 | (check-expect (sorted-list (apply heap > int-list)) 76 | (reverse int-list)) 77 | 78 | (check-expect (fold + 0 (heap < 1 1 1 10 1 15)) 29) 79 | (check-expect (sorted-list (map < add1 (heap < 10 4 5 14 29 15))) 80 | (list 5 6 11 15 16 30)) 81 | (check-expect (fold + 0 (heap > 1)) 1) 82 | (check-expect (sorted-list (filter even? (heap < 10 4 5 14 29 15))) 83 | (list 4 10 14)) 84 | (check-expect (sorted-list (remove odd? (heap < 10 4 5 14 29 15))) 85 | (list 4 10 14)) 86 | (check-expect (sorted-list (remove even? (heap < 10 4 5 14 29 15))) 87 | (list 5 15 29)) 88 | (check-expect (sorted-list (filter odd? (heap < 10 4 5 14 29 15))) 89 | (list 5 15 29)) 90 | 91 | (check-expect (ormap odd? (heap < 10 4 5 14 29 15)) #t) 92 | (check-expect (ormap even? (heap < 5 29 15)) #f) 93 | (check-expect (andmap odd? (heap < 5 29 15)) #t) 94 | (check-expect (andmap odd? (heap < 5 29 14)) #f) 95 | 96 | (test) 97 | -------------------------------------------------------------------------------- /pfds/tests/bootstrapedheap-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require pfds/heap/bootstrapped) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | 6 | (: less-than? : (Integer Integer -> Boolean)) 7 | (define (less-than? a b) 8 | (<= a b)) 9 | 10 | (: gt : (Integer Integer -> Boolean)) 11 | (define (gt a b) 12 | (> a b)) 13 | 14 | (: str-less-than? : (String String -> Boolean)) 15 | (define (str-less-than? a b) 16 | (string<=? a b)) 17 | 18 | (check-expect (find-min/max (heap less-than? 1 2 3 4)) 1) 19 | (check-expect (find-min/max (heap less-than? 1 2 3 0)) 0) 20 | (check-expect (find-min/max (heap less-than? 1 2 -3 4)) -3) 21 | (check-error (find-min/max (delete-min/max (heap less-than? 1))) 22 | "find-min/max: given heap is empty") 23 | 24 | (check-expect (sorted-list (delete-min/max 25 | (heap less-than? 1 2 3 4))) 26 | (list 2 3 4)) 27 | (check-expect (sorted-list (delete-min/max 28 | (heap less-than? 1 2 3 0))) 29 | (list 1 2 3)) 30 | (check-expect (sorted-list (delete-min/max 31 | (heap less-than? 1 2 -3 4))) 32 | (list 1 2 4)) 33 | (check-error (delete-min/max (delete-min/max 34 | (heap less-than? 1))) 35 | "delete-min/max: given heap is empty") 36 | 37 | (check-expect (sorted-list (delete-min/max 38 | (heap less-than? 1))) (list)) 39 | (check-expect (sorted-list (delete-min/max 40 | (heap less-than? 1 -2 -3 -4))) 41 | (list -3 -2 1)) 42 | 43 | (check-expect (sorted-list (insert 10 44 | (ann (heap less-than? 1 -2 -3 -4) 45 | (Heap Integer)))) 46 | (list -4 -3 -2 1 10)) 47 | 48 | (check-expect (sorted-list (insert -10 49 | (heap less-than? 1 20 -3 -4))) 50 | (list -10 -4 -3 1 20)) 51 | 52 | (check-expect (sorted-list (insert 1 (heap less-than? 1 2 -3 -4))) 53 | (list -4 -3 1 1 2)) 54 | 55 | (check-expect (sorted-list (merge (ann (heap less-than? 2 3 -1 -10) 56 | (Heap Integer)) 57 | (ann (heap less-than? 1 -2 -3 -4) 58 | (Heap Integer)))) 59 | (list -10 -4 -3 -2 -1 1 2 3)) 60 | 61 | (check-expect (sorted-list 62 | (merge (delete-min/max 63 | (ann (heap less-than? -1 5) 64 | (Heap Integer))) 65 | (ann (heap less-than? 1 -2 -3 -4) 66 | (Heap Integer)))) 67 | (list -4 -3 -2 1 5)) 68 | 69 | (check-expect (sorted-list (merge (ann (heap less-than? 1 -2 -3 -4) 70 | (Heap Integer)) 71 | (delete-min/max 72 | (ann (heap less-than? -1 2) 73 | (Heap Integer))))) 74 | (list -4 -3 -2 1 2)) 75 | 76 | (define int-list (build-list 100 (λ: ([x : Integer]) x))) 77 | (define int-list1 (build-list 100 (λ: ([x : Integer]) (+ x 100)))) 78 | 79 | (check-expect (sorted-list (apply heap less-than? int-list)) 80 | int-list) 81 | 82 | (check-expect (sorted-list (apply heap gt int-list)) 83 | (reverse int-list)) 84 | 85 | (check-expect (sorted-list (merge 86 | (apply heap less-than? int-list) 87 | (apply heap less-than? int-list1))) 88 | (append int-list int-list1)) 89 | 90 | (check-expect (fold + 0 (heap < 1 1 1 10 1 15)) 29) 91 | (check-expect (sorted-list (map < add1 (heap < 10 4 5 14 29 15))) 92 | (list 5 6 11 15 16 30)) 93 | (check-expect (fold + 0 (heap > 1)) 1) 94 | (check-expect (sorted-list (filter even? (heap < 10 4 5 14 29 15))) 95 | (list 4 10 14)) 96 | (check-expect (sorted-list (remove odd? (heap < 10 4 5 14 29 15))) 97 | (list 4 10 14)) 98 | (check-expect (sorted-list (remove even? (heap < 10 4 5 14 29 15))) 99 | (list 5 15 29)) 100 | (check-expect (sorted-list (filter odd? (heap < 10 4 5 14 29 15))) 101 | (list 5 15 29)) 102 | 103 | (check-expect (ormap odd? (heap < 10 4 5 14 29 15)) #t) 104 | (check-expect (ormap even? (heap < 5 29 15)) #f) 105 | (check-expect (andmap odd? (heap < 5 29 15)) #t) 106 | (check-expect (andmap odd? (heap < 5 29 14)) #f) 107 | 108 | (test) 109 | -------------------------------------------------------------------------------- /pfds/tests/bootstrapedqueue-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require pfds/queue/bootstrapped) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | (check-expect (empty? empty) #t) 6 | (check-expect (empty? (queue 1)) #f) 7 | (check-expect (empty? (queue 1 2)) #f) 8 | 9 | (check-expect (head (queue 4 5 2 3)) 4) 10 | (check-expect (head (queue 2)) 2) 11 | 12 | (check-expect (queue->list (tail (queue 4 5 2 3))) 13 | (list 5 2 3)) 14 | (check-expect (queue->list (tail (queue 1))) null) 15 | (check-error (tail (tail (queue 1))) "tail: given queue is empty") 16 | 17 | (check-expect (queue->list (enqueue 1 empty)) (list 1)) 18 | (check-expect (queue->list (enqueue 1 (queue 1 2 3))) (list 1 2 3 1)) 19 | 20 | (check-expect (head (enqueue 1 empty)) 1) 21 | (check-expect (head (enqueue 10 (queue 5 2 3))) 5) 22 | 23 | (check-error (head (tail (queue 1))) "head: given queue is empty") 24 | 25 | (check-expect (queue->list (map + (queue 1 2 3 4 5) (queue 1 2 3 4 5))) 26 | (list 2 4 6 8 10)) 27 | 28 | (check-expect (queue->list (map - (queue 1 2 3 4 5) (queue 1 2 3 4 5))) 29 | (list 0 0 0 0 0)) 30 | 31 | (check-expect (fold + 0 (queue 1 2 3 4 5)) 15) 32 | 33 | (check-expect (fold + 0 (queue 1 2 3 4 5) (queue 1 2 3 4 5)) 30) 34 | 35 | (check-expect (queue->list (filter positive? (queue 1 2 -4 5 0 -6 12 3 -2))) 36 | (list 1 2 5 12 3)) 37 | 38 | (check-expect (queue->list (filter negative? (queue 1 2 -4 5 0 -6 12 3 -2))) 39 | (list -4 -6 -2)) 40 | 41 | (check-expect (queue->list (remove positive? (queue 1 2 -4 5 0 -6 12 3 -2))) 42 | (list -4 0 -6 -2)) 43 | 44 | (check-expect (queue->list (remove negative? (queue 1 2 -4 5 0 -6 12 3 -2))) 45 | (list 1 2 5 0 12 3)) 46 | 47 | (test) 48 | -------------------------------------------------------------------------------- /pfds/tests/catenablelist-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/scheme 2 | (require (prefix-in rk: racket/base)) 3 | (require pfds/catenable-list) 4 | (require typed/test-engine/scheme-tests) 5 | 6 | (check-expect (first (list 1 2 3 4 5 6 7)) 1) 7 | (check-expect (first (list "" "")) "") 8 | (check-expect (rest (list 1)) empty) 9 | (check-expect (first (rest (list 1 2 3 4 5 6 7))) 2) 10 | 11 | (check-expect (empty? (rest (list 1))) #t) 12 | (check-expect (empty? (rest (list 2 1))) #f) 13 | (check-expect (empty? empty) #t) 14 | (check-error (first empty) "first: given list is empty") 15 | (check-error (rest empty) "rest: given list is empty") 16 | (check-expect (->list (rest (list 1 2 3 4 5 6 7))) 17 | (rk:list 2 3 4 5 6 7)) 18 | 19 | (check-expect (->list (rest (rest (list 1 2 3 4 5 6 7)))) 20 | (rk:list 3 4 5 6 7)) 21 | 22 | (check-expect (->list (append (ann (list 1) (CatenableList Integer)) 23 | (ann (list 1 2 3 4 5 6 7) 24 | (CatenableList Integer)))) 25 | (rk:list 1 1 2 3 4 5 6 7)) 26 | 27 | (check-expect (->list (append empty 28 | (list 1 2 3 4 5 6 7))) 29 | (rk:list 1 2 3 4 5 6 7)) 30 | 31 | (check-expect (->list (append (list 1 2 3 4 5 6 7) empty)) 32 | (rk:list 1 2 3 4 5 6 7)) 33 | 34 | (check-expect (->list (append empty empty)) null) 35 | 36 | (check-expect (->list (cons-to-end 10 (list 1 2 3 4 5 6 7))) 37 | (rk:list 1 2 3 4 5 6 7 10)) 38 | 39 | (check-expect (->list (cons-to-end 1 (list 1 2 3))) 40 | (rk:list 1 2 3 1)) 41 | 42 | (check-expect (->list (cons 5 (ann (list 1) 43 | (CatenableList Integer)))) 44 | (rk:list 5 1)) 45 | 46 | (check-expect (->list (cons-to-end 0 empty)) (rk:list 0)) 47 | 48 | (check-expect (->list (cons 0 empty)) (rk:list 0)) 49 | 50 | (define lst (rk:build-list 100 (λ: ([x : Integer]) x))) 51 | (define lst1 (rk:build-list 100 (λ: ([x : Integer]) (+ x 100)))) 52 | (check-expect (->list (apply list lst)) lst) 53 | 54 | (check-expect (->list (append (apply list lst) (apply list lst1))) 55 | (rk:append lst lst1)) 56 | 57 | (test) 58 | -------------------------------------------------------------------------------- /pfds/tests/hood-melville-queue-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require pfds/queue/hood-melville) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | (check-expect (empty? empty) #t) 6 | (check-expect (empty? (queue 1)) #f) 7 | (check-expect (empty? (queue 1 2)) #f) 8 | 9 | (check-expect (head (queue 4 5 2 3)) 4) 10 | (check-expect (head (queue 2)) 2) 11 | 12 | (check-expect (queue->list (tail (queue 4 5 2 3))) 13 | (list 5 2 3)) 14 | (check-expect (queue->list (tail (queue 1))) null) 15 | (check-error (tail empty) "tail: given queue is empty") 16 | 17 | (check-expect (queue->list (enqueue 1 empty)) (list 1)) 18 | (check-expect (queue->list (enqueue 1 (queue 1 2 3))) (list 1 2 3 1)) 19 | 20 | (check-expect (head (enqueue 1 empty)) 1) 21 | (check-expect (head (enqueue 10 (queue 5 2 3))) 5) 22 | 23 | (check-error (head empty) "head: given queue is empty") 24 | 25 | (define lst (build-list 100 (λ: ([x : Integer]) x))) 26 | 27 | (check-expect (queue->list (apply queue lst)) lst) 28 | 29 | (check-expect (queue->list (map + (queue 1 2 3 4 5) (queue 1 2 3 4 5))) 30 | (list 2 4 6 8 10)) 31 | 32 | (check-expect (queue->list (map - (queue 1 2 3 4 5) (queue 1 2 3 4 5))) 33 | (list 0 0 0 0 0)) 34 | 35 | (check-expect (fold + 0 (queue 1 2 3 4 5)) 15) 36 | 37 | (check-expect (fold + 0 (queue 1 2 3 4 5) (queue 1 2 3 4 5)) 30) 38 | 39 | (test) 40 | -------------------------------------------------------------------------------- /pfds/tests/implicitdeque-performance-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | (require pfds/deque/implicit) 3 | 4 | 5 | ;; tests run with Racket 5.3.0.11, in DrRacket, 6 | ;; on a Intel i7-920 processor machine with 12GB memory 7 | 8 | 9 | ;;;;; test enqueue 10 | 11 | ; with bug 12 | ; cpu time: 19828 real time: 19856 gc time: 9329 13 | 14 | ; bug fixed (let* moved inside delay) 15 | ; cpu time: 2797 real time: 2809 gc time: 532 16 | 17 | (time (build-deque 1000000 add1)) 18 | 19 | 20 | ;;;;; test enqueue-front 21 | 22 | ; with bug 23 | ; cpu time: 49500 real time: 49721 gc time: 15297 24 | 25 | ; bug fixed (let* moved inside delay) 26 | ; cpu time: 26953 real time: 26983 gc time: 2489 27 | 28 | (time 29 | (for/fold ([dq (deque)]) ([i (in-range 1000000)]) 30 | (enqueue-front i dq))) 31 | -------------------------------------------------------------------------------- /pfds/tests/implicitdeque-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require pfds/deque/implicit) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | (check-expect (empty? empty) #t) 6 | (check-expect (empty? (deque 1)) #f) 7 | (check-expect (head (deque 1)) 1) 8 | (check-expect (last (deque 1)) 1) 9 | (check-expect (head (deque 4 5 1 2 -1)) 4) 10 | (check-expect (head (tail (deque 4 5 1 2 -1))) 5) 11 | (check-expect (last (deque 4 5 1 2 -1)) -1) 12 | (check-expect (last (init (deque 4 5 1 2 -1))) 2) 13 | (check-expect (head (tail (init (deque 4 5 1 2 -1)))) 5) 14 | (check-expect (last (tail (init (deque 4 5 1 2 -1)))) 2) 15 | 16 | (check-error (head (tail (deque 1))) "head: given deque is empty") 17 | (check-error (last (tail (deque 1))) "last: given deque is empty") 18 | (check-error (tail (tail (deque 1))) "tail: given deque is empty") 19 | (check-error (init (tail (deque 1))) "init: given deque is empty") 20 | 21 | (check-expect (deque->list (tail (deque 1))) null) 22 | (check-expect (deque->list (init (deque 1))) null) 23 | (check-expect (deque->list (tail (deque 1 2 3 4))) 24 | (list 2 3 4)) 25 | (check-expect (deque->list (init (deque 1 2 3 4))) 26 | (list 1 2 3)) 27 | 28 | (check-expect (deque->list (enqueue 1 empty)) (list 1)) 29 | (check-expect (deque->list (enqueue-front 10 (enqueue-front 1 empty))) 30 | (list 10 1)) 31 | (check-expect (deque->list (enqueue 1 (deque 2))) (list 2 1)) 32 | (check-expect (deque->list (enqueue-front 1 (deque 2 3 4 5))) 33 | (list 1 2 3 4 5)) 34 | (check-expect (deque->list (enqueue 10 (enqueue 1 (deque 2 3 4 5)))) 35 | (list 2 3 4 5 1 10)) 36 | (check-expect (deque->list (enqueue-front 1 (deque 2 3))) 37 | (list 1 2 3)) 38 | 39 | (define lst (build-list 100 (λ(x) x))) 40 | (check-expect (deque->list (apply deque lst)) lst) 41 | 42 | (check-expect (deque->rev-list (apply deque lst)) (reverse lst)) 43 | 44 | (check-expect (deque->list (map + (deque 1 2 3 4 5) (deque 1 2 3 4 5))) 45 | (list 2 4 6 8 10)) 46 | 47 | (check-expect (deque->list (map - (deque 1 2 3 4 5) (deque 1 2 3 4 5))) 48 | (list 0 0 0 0 0)) 49 | 50 | (check-expect (foldl + 0 (deque 1 2 3 4 5)) 15) 51 | 52 | (check-expect (foldl - 2 (deque 1 2 3 4 5)) -13) 53 | 54 | (check-expect (foldr + 0 (deque 1 2 3 4 5)) 15) 55 | 56 | (check-expect (foldr + 0 (deque 1 2 3 4 5) (deque 1 2 3 4 5)) 30) 57 | 58 | (check-expect (deque->list (filter positive? (deque 1 2 -4 5 0 -6 12 3 -2))) 59 | (list 1 2 5 12 3)) 60 | 61 | (check-expect (deque->list (filter negative? (deque 1 2 -4 5 0 -6 12 3 -2))) 62 | (list -4 -6 -2)) 63 | 64 | (check-expect (deque->list (remove positive? (deque 1 2 -4 5 0 -6 12 3 -2))) 65 | (list -4 0 -6 -2)) 66 | 67 | (check-expect (deque->list (remove negative? (deque 1 2 -4 5 0 -6 12 3 -2))) 68 | (list 1 2 5 0 12 3)) 69 | 70 | (test) 71 | -------------------------------------------------------------------------------- /pfds/tests/implicitqueue-performance-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | (require pfds/queue/implicit) 3 | 4 | 5 | ;; tests run with Racket 5.3.0.11, in DrRacket, 6 | ;; on a Intel i7-920 processor machine with 12GB memory 7 | 8 | 9 | ;;;;; test enqueue 10 | 11 | ; with bug 12 | ; cpu time: 22234 real time: 22320 gc time: 11126 13 | 14 | ; bug fixed (let* moved inside delay) 15 | ; cpu time: 4703 real time: 4704 gc time: 1442 16 | 17 | (time (build-queue 1000000 add1)) 18 | -------------------------------------------------------------------------------- /pfds/tests/implicitqueue-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require pfds/queue/implicit) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | (check-expect (empty? empty) #t) 6 | (check-expect (empty? (queue 1)) #f) 7 | (check-expect (head (queue 1)) 1) 8 | (check-error (head empty) "head: given queue is empty") 9 | (check-expect (head (queue 1 2)) 1) 10 | (check-expect (head (queue 10 2 34 55)) 10) 11 | 12 | (check-expect (queue->list (tail (queue 1))) null) 13 | (check-error (tail empty) "tail: given queue is empty") 14 | (check-expect (queue->list (tail (queue 10 12))) (list 12)) 15 | (check-expect (queue->list (tail (queue 23 45 -6))) (list 45 -6)) 16 | (check-expect (queue->list (tail (queue 23 45 -6 15))) 17 | (list 45 -6 15)) 18 | 19 | (check-expect (queue->list (enqueue 10 (queue 23 45 -6 15))) 20 | (list 23 45 -6 15 10)) 21 | (check-expect (queue->list (enqueue 10 empty)) (list 10)) 22 | 23 | (check-expect (queue->list (enqueue 10 (queue 20))) 24 | (list 20 10)) 25 | (check-expect (queue->list (apply queue (build-list 100 (λ(x) x)))) 26 | (build-list 100 (λ(x) x))) 27 | 28 | (check-expect (queue->list (map + (queue 1 2 3 4 5) (queue 1 2 3 4 5))) 29 | (list 2 4 6 8 10)) 30 | 31 | (check-expect (queue->list (map - (queue 1 2 3 4 5) (queue 1 2 3 4 5))) 32 | (list 0 0 0 0 0)) 33 | 34 | (check-expect (fold + 0 (queue 1 2 3 4 5)) 15) 35 | 36 | 37 | (check-expect (queue->list (filter positive? (queue 1 2 -4 5 0 -6 12 3 -2))) 38 | (list 1 2 5 12 3)) 39 | 40 | (check-expect (queue->list (filter negative? (queue 1 2 -4 5 0 -6 12 3 -2))) 41 | (list -4 -6 -2)) 42 | 43 | (check-expect (queue->list (remove positive? (queue 1 2 -4 5 0 -6 12 3 -2))) 44 | (list -4 0 -6 -2)) 45 | 46 | (check-expect (queue->list (remove negative? (queue 1 2 -4 5 0 -6 12 3 -2))) 47 | (list 1 2 5 0 12 3)) 48 | (check-expect (fold + 0 (queue 1 2 3 4 5) (queue 1 2 3 4 5)) 30) 49 | (test) 50 | -------------------------------------------------------------------------------- /pfds/tests/lazypairingheap-test.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/scheme 2 | (require pfds/heap/lazy-pairing) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | 6 | (check-expect 7 | (sorted-list (apply heap 8 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 9 | (build-list 100 (λ: ([x : Integer]) x)))) 10 | (build-list 100 (λ(x) x))) 11 | 12 | (check-expect 13 | (sorted-list (merge (apply heap 14 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 15 | (build-list 100 (λ: ([x : Integer]) x))) 16 | (apply heap 17 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 18 | (build-list 100 (λ: ([x : Integer]) (+ 100 x)))))) 19 | (append (build-list 100 (λ(x) x)) 20 | (build-list 100 (λ: ([x : Integer]) (+ 100 x))))) 21 | 22 | (check-expect 23 | (sorted-list 24 | (delete-min/max 25 | (merge (apply heap 26 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 27 | (build-list 100 (λ: ([x : Integer]) x))) 28 | (apply heap 29 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 30 | (build-list 100 (λ: ([x : Integer]) (+ 100 x))))))) 31 | (append (cdr (build-list 100 (λ(x) x))) 32 | (build-list 100 (λ: ([x : Integer]) (+ 100 x))))) 33 | 34 | 35 | (check-expect 36 | (sorted-list 37 | (delete-min/max 38 | (delete-min/max 39 | (merge (apply heap 40 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 41 | (build-list 100 (λ: ([x : Integer]) x))) 42 | (apply heap 43 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 44 | (build-list 100 (λ: ([x : Integer]) (- x 100)))))))) 45 | (append (build-list 98 (λ: ([x : Integer]) (- x 98))) 46 | (build-list 100 (λ(x) x)))) 47 | 48 | (check-expect 49 | (sorted-list 50 | (insert 51 | 500 52 | (delete-min/max 53 | (delete-min/max 54 | (merge (apply heap 55 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 56 | (build-list 100 (λ: ([x : Integer]) x))) 57 | (apply heap 58 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 59 | (build-list 100 (λ: ([x : Integer]) (- x 100))))))))) 60 | (append (build-list 98 (λ: ([x : Integer]) (- x 98))) 61 | (build-list 100 (λ(x) x)) 62 | (cons 500 null))) 63 | 64 | (check-error 65 | (delete-min/max (heap (λ: ([a : Integer] [b : Integer]) (<= a b)))) 66 | "delete-min/max: given heap is empty") 67 | 68 | (check-error 69 | (find-min/max (heap (λ: ([a : Integer] [b : Integer]) (<= a b)))) 70 | "find-min/max: given heap is empty") 71 | 72 | (check-expect (fold + 0 (heap < 1 1 1 10 1 15)) 29) 73 | (check-expect (sorted-list (map < add1 (heap < 10 4 5 14 29 15))) 74 | (list 5 6 11 15 16 30)) 75 | (check-expect (fold + 0 (heap > 1)) 1) 76 | (check-expect (sorted-list (filter even? (heap < 10 4 5 14 29 15))) 77 | (list 4 10 14)) 78 | (check-expect (sorted-list (remove odd? (heap < 10 4 5 14 29 15))) 79 | (list 4 10 14)) 80 | (check-expect (sorted-list (remove even? (heap < 10 4 5 14 29 15))) 81 | (list 5 15 29)) 82 | (check-expect (sorted-list (filter odd? (heap < 10 4 5 14 29 15))) 83 | (list 5 15 29)) 84 | 85 | (check-expect (ormap odd? (heap < 10 4 5 14 29 15)) #t) 86 | (check-expect (ormap even? (heap < 5 29 15)) #f) 87 | (check-expect (andmap odd? (heap < 5 29 15)) #t) 88 | (check-expect (andmap odd? (heap < 5 29 14)) #f) 89 | 90 | (test) 91 | -------------------------------------------------------------------------------- /pfds/tests/leftistheaps-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/scheme 2 | (require pfds/heap/leftist) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | (define lst (build-list 100 (λ: ([x : Integer]) x))) 6 | (check-expect 7 | (sorted-list (apply heap 8 | (λ: ([a : Integer] [b : Integer]) (<= a b)) lst)) lst) 9 | 10 | (check-expect 11 | (sorted-list (merge (apply heap 12 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 13 | (build-list 100 (λ: ([x : Integer]) x))) 14 | (apply heap 15 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 16 | (build-list 100 (λ: ([x : Integer]) (+ 100 x)))))) 17 | (append (build-list 100 (λ(x) x)) 18 | (build-list 100 (λ: ([x : Integer]) (+ 100 x))))) 19 | 20 | (check-expect 21 | (sorted-list 22 | (delete-min/max 23 | (merge (apply heap 24 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 25 | (build-list 100 (λ: ([x : Integer]) x))) 26 | (apply heap 27 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 28 | (build-list 100 (λ: ([x : Integer]) (+ 100 x))))))) 29 | (append (cdr (build-list 100 (λ(x) x))) 30 | (build-list 100 (λ: ([x : Integer]) (+ 100 x))))) 31 | 32 | 33 | (check-expect 34 | (sorted-list 35 | (delete-min/max 36 | (delete-min/max 37 | (merge (apply heap 38 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 39 | (build-list 100 (λ: ([x : Integer]) x))) 40 | (apply heap 41 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 42 | (build-list 100 (λ: ([x : Integer]) (- x 100)))))))) 43 | (append (build-list 98 (λ: ([x : Integer]) (- x 98))) 44 | (build-list 100 (λ(x) x)))) 45 | 46 | (check-expect 47 | (sorted-list 48 | (insert 49 | 500 50 | (delete-min/max 51 | (delete-min/max 52 | (merge (apply heap 53 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 54 | (build-list 100 (λ: ([x : Integer]) x))) 55 | (apply heap 56 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 57 | (build-list 100 (λ: ([x : Integer]) (- x 100))))))))) 58 | (append (build-list 98 (λ: ([x : Integer]) (- x 98))) 59 | (build-list 100 (λ(x) x)) 60 | (cons 500 null))) 61 | 62 | (check-error 63 | (delete-min/max (heap (λ: ([a : Integer] [b : Integer]) (<= a b)))) 64 | "delete-min/max: given heap is empty") 65 | 66 | (check-error 67 | (find-min/max (heap (λ: ([a : Integer] [b : Integer]) (<= a b)))) 68 | "find-min/max: given heap is empty") 69 | 70 | (check-expect (fold + 0 (heap < 1 1 1 10 1 15)) 29) 71 | (check-expect (sorted-list (map < add1 (heap < 10 4 5 14 29 15))) 72 | (list 5 6 11 15 16 30)) 73 | (check-expect (fold + 0 (heap > 1)) 1) 74 | (check-expect (sorted-list (filter even? (heap < 10 4 5 14 29 15))) 75 | (list 4 10 14)) 76 | (check-expect (sorted-list (remove odd? (heap < 10 4 5 14 29 15))) 77 | (list 4 10 14)) 78 | (check-expect (sorted-list (remove even? (heap < 10 4 5 14 29 15))) 79 | (list 5 15 29)) 80 | (check-expect (sorted-list (filter odd? (heap < 10 4 5 14 29 15))) 81 | (list 5 15 29)) 82 | 83 | (check-expect (ormap odd? (heap < 10 4 5 14 29 15)) #t) 84 | (check-expect (ormap even? (heap < 5 29 15)) #f) 85 | (check-expect (andmap odd? (heap < 5 29 15)) #t) 86 | (check-expect (andmap odd? (heap < 5 29 14)) #f) 87 | 88 | (test) 89 | -------------------------------------------------------------------------------- /pfds/tests/pairingheap-test.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require pfds/heap/pairing) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | 6 | (check-expect 7 | (sorted-list (apply heap 8 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 9 | (build-list 100 (λ: ([x : Integer]) x)))) 10 | (build-list 100 (λ(x) x))) 11 | 12 | (check-expect 13 | (sorted-list (merge (apply heap 14 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 15 | (build-list 100 (λ: ([x : Integer]) x))) 16 | (apply heap 17 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 18 | (build-list 100 (λ: ([x : Integer]) (+ 100 x)))))) 19 | (append (build-list 100 (λ(x) x)) 20 | (build-list 100 (λ: ([x : Integer]) (+ 100 x))))) 21 | 22 | (check-expect 23 | (sorted-list 24 | (delete-min/max 25 | (merge (apply heap 26 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 27 | (build-list 100 (λ: ([x : Integer]) x))) 28 | (apply heap 29 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 30 | (build-list 100 (λ: ([x : Integer]) (+ 100 x))))))) 31 | (append (cdr (build-list 100 (λ(x) x))) 32 | (build-list 100 (λ: ([x : Integer]) (+ 100 x))))) 33 | 34 | 35 | (check-expect 36 | (sorted-list 37 | (delete-min/max 38 | (delete-min/max 39 | (merge (apply heap 40 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 41 | (build-list 100 (λ: ([x : Integer]) x))) 42 | (apply heap 43 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 44 | (build-list 100 (λ: ([x : Integer]) (- x 100)))))))) 45 | (append (build-list 98 (λ: ([x : Integer]) (- x 98))) 46 | (build-list 100 (λ(x) x)))) 47 | 48 | (check-expect 49 | (sorted-list 50 | (insert 51 | 500 52 | (delete-min/max 53 | (delete-min/max 54 | (merge (apply heap 55 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 56 | (build-list 100 (λ: ([x : Integer]) x))) 57 | (apply heap 58 | (λ: ([a : Integer] [b : Integer]) (<= a b)) 59 | (build-list 100 (λ: ([x : Integer]) (- x 100))))))))) 60 | (append (build-list 98 (λ: ([x : Integer]) (- x 98))) 61 | (build-list 100 (λ(x) x)) 62 | (cons 500 null))) 63 | 64 | (check-error 65 | (delete-min/max (heap (λ: ([a : Integer] [b : Integer]) (<= a b)))) 66 | "delete-min/max: given heap is empty") 67 | 68 | (check-error 69 | (find-min/max (heap (λ: ([a : Integer] [b : Integer]) (<= a b)))) 70 | "find-min/max: given heap is empty") 71 | 72 | (check-expect (fold + 0 (heap < 1 1 1 10 1 15)) 29) 73 | (check-expect (sorted-list (map < add1 (heap < 10 4 5 14 29 15))) 74 | (list 5 6 11 15 16 30)) 75 | (check-expect (fold + 0 (heap > 1)) 1) 76 | (check-expect (sorted-list (filter even? (heap < 10 4 5 14 29 15))) 77 | (list 4 10 14)) 78 | (check-expect (sorted-list (remove odd? (heap < 10 4 5 14 29 15))) 79 | (list 4 10 14)) 80 | (check-expect (sorted-list (remove even? (heap < 10 4 5 14 29 15))) 81 | (list 5 15 29)) 82 | (check-expect (sorted-list (filter odd? (heap < 10 4 5 14 29 15))) 83 | (list 5 15 29)) 84 | 85 | (check-expect (ormap odd? (heap < 10 4 5 14 29 15)) #t) 86 | (check-expect (ormap even? (heap < 5 29 15)) #f) 87 | (check-expect (andmap odd? (heap < 5 29 15)) #t) 88 | (check-expect (andmap odd? (heap < 5 29 14)) #f) 89 | 90 | (test) 91 | -------------------------------------------------------------------------------- /pfds/tests/partialstream-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | (require "../delay.rkt") 4 | (require "../partialstream.rkt") 5 | (require typed/rackunit) 6 | 7 | (: sum : ((PartialStreamof Integer) -> Integer)) 8 | (define (sum lst) 9 | (if (null? lst) 10 | 0 11 | (+ (pscar lst) (sum (pscdr lst))))) 12 | 13 | (define-syntax-rule (check-type e t) (check-equal? (ann e t) e)) 14 | 15 | (check-type (list 1 2 3) (Listof Integer)) 16 | (check-type (list 1 2 3) (PartialStreamof Integer)) 17 | (check-type (reverse (list 1 2 3)) (Listof Integer)) 18 | (check-type (reverse (list 1 2 3)) (PartialStreamof Integer)) 19 | 20 | (check-equal? 21 | (sum 22 | (psappend 23 | (ann (delay (ann (reverse (list 1 2 3)) (PartialStreamof Integer))) 24 | (PartialStreamof Integer)) 25 | (ann (delay (ann (reverse (list 4 5 6)) (PartialStreamof Integer))) 26 | (PartialStreamof Integer)))) 27 | 21) -------------------------------------------------------------------------------- /pfds/tests/physicists-queue-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require pfds/queue/physicists) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | (check-expect (empty? (empty Nothing)) #t) 6 | (check-expect (empty? (queue 1)) #f) 7 | (check-expect (empty? (queue 1 2)) #f) 8 | 9 | (check-expect (head (queue 1)) 1) 10 | (check-expect (head (queue 4 1 2)) 4) 11 | (check-error (head (list->queue (list))) "head: given queue is empty") 12 | 13 | (check-expect (queue->list (tail (queue 1))) null) 14 | (check-expect (queue->list (tail (queue 4 1 2))) (list 1 2)) 15 | (check-expect (queue->list (tail (queue 4 1 2 10 15 23 -10))) 16 | (list 1 2 10 15 23 -10)) 17 | (check-error (tail (list->queue (list))) "tail: given queue is empty") 18 | 19 | 20 | (check-expect (queue->list (enqueue 1 (empty Integer))) (list 1)) 21 | (check-expect (queue->list (enqueue 1 (queue 4 1 2))) (list 4 1 2 1)) 22 | (check-expect (queue->list (enqueue 1 (queue 4 1 2 5))) 23 | (list 4 1 2 5 1)) 24 | 25 | (check-expect (queue->list (queue '(1) '(2 2) '(3 4) '(5 6 7) '(5))) 26 | (list '(1) '(2 2) '(3 4) '(5 6 7) '(5))) 27 | 28 | (check-expect (queue->list (map + (queue 1 2 3 4 5) (queue 1 2 3 4 5))) 29 | (list 2 4 6 8 10)) 30 | 31 | (check-expect (queue->list (map - (queue 1 2 3 4 5) (queue 1 2 3 4 5))) 32 | (list 0 0 0 0 0)) 33 | 34 | (check-expect (fold + 0 (queue 1 2 3 4 5)) 15) 35 | 36 | 37 | (check-expect (queue->list (filter positive? (queue 1 2 -4 5 0 -6 12 3 -2))) 38 | (list 1 2 5 12 3)) 39 | 40 | (check-expect (queue->list (filter negative? (queue 1 2 -4 5 0 -6 12 3 -2))) 41 | (list -4 -6 -2)) 42 | 43 | (check-expect (queue->list (remove positive? (queue 1 2 -4 5 0 -6 12 3 -2))) 44 | (list -4 0 -6 -2)) 45 | 46 | (check-expect (queue->list (remove negative? (queue 1 2 -4 5 0 -6 12 3 -2))) 47 | (list 1 2 5 0 12 3)) 48 | (check-expect (fold + 0 (queue 1 2 3 4 5) (queue 1 2 3 4 5)) 30) 49 | (test) 50 | -------------------------------------------------------------------------------- /pfds/tests/realtimedeque-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require pfds/deque/real-time) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | (check-expect (empty? (empty Nothing)) #t) 6 | (check-expect (empty? (deque 1)) #f) 7 | (check-expect (head (deque 1)) 1) 8 | (check-expect (last (deque 1)) 1) 9 | (check-expect (head (deque 4 5 1 2 -1)) 4) 10 | (check-expect (head (tail (deque 4 5 1 2 -1))) 5) 11 | (check-expect (last (deque 4 5 1 2 -1)) -1) 12 | (check-expect (last (init (deque 4 5 1 2 -1))) 2) 13 | (check-expect (head (tail (init (deque 4 5 1 2 -1)))) 5) 14 | (check-expect (last (tail (init (deque 4 5 1 2 -1)))) 2) 15 | 16 | (check-error (head (empty Nothing)) "head: given deque is empty") 17 | (check-error (last (empty Nothing)) "last: given deque is empty") 18 | (check-error (tail (empty Nothing)) "tail: given deque is empty") 19 | (check-error (init (empty Nothing)) "init: given deque is empty") 20 | 21 | (check-expect (deque->list (tail (deque 1))) null) 22 | (check-expect (deque->list (init (deque 1))) null) 23 | (check-expect (deque->list (tail (deque 1 2 3 4))) (list 2 3 4)) 24 | (check-expect (deque->list (init (deque 1 2 3 4))) (list 1 2 3)) 25 | 26 | (check-expect (deque->list (enqueue 1 (empty Integer))) (list 1)) 27 | (check-expect (deque->list (enqueue-front 1 (empty Integer))) (list 1)) 28 | (check-expect (deque->list (enqueue 1 (deque 2))) (list 2 1)) 29 | (check-expect (deque->list (enqueue-front 1 (deque 2))) (list 1 2)) 30 | (check-expect (deque->list (enqueue 1 (deque 2 3))) (list 2 3 1)) 31 | (check-expect (deque->list (enqueue-front 1 (deque 2 3))) (list 1 2 3)) 32 | 33 | (define lst (build-list 100 (λ: ([x : Integer]) x))) 34 | 35 | (check-expect (deque->list (apply deque lst)) lst) 36 | 37 | (check-expect (deque->list (map + (deque 1 2 3 4 5) (deque 1 2 3 4 5))) 38 | (list 2 4 6 8 10)) 39 | 40 | (check-expect (deque->list (map - (deque 1 2 3 4 5) (deque 1 2 3 4 5))) 41 | (list 0 0 0 0 0)) 42 | 43 | (check-expect (foldl + 0 (deque 1 2 3 4 5)) 15) 44 | 45 | (check-expect (foldl - 2 (deque 1 2 3 4 5)) -13) 46 | 47 | (check-expect (foldr + 0 (deque 1 2 3 4 5)) 15) 48 | 49 | (check-expect (foldr + 0 (deque 1 2 3 4 5) (deque 1 2 3 4 5)) 30) 50 | 51 | (check-expect (deque->list (filter positive? (deque 1 2 -4 5 0 -6 12 3 -2))) 52 | (list 1 2 5 12 3)) 53 | 54 | (check-expect (deque->list (filter negative? (deque 1 2 -4 5 0 -6 12 3 -2))) 55 | (list -4 -6 -2)) 56 | 57 | (check-expect (deque->list (remove positive? (deque 1 2 -4 5 0 -6 12 3 -2))) 58 | (list -4 0 -6 -2)) 59 | 60 | (check-expect (deque->list (remove negative? (deque 1 2 -4 5 0 -6 12 3 -2))) 61 | (list 1 2 5 0 12 3)) 62 | 63 | (test) 64 | -------------------------------------------------------------------------------- /pfds/tests/realtimequeue-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require pfds/queue/real-time) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | (check-expect (empty? (empty Integer)) #t) 6 | (check-expect (empty? (queue 1)) #f) 7 | (check-expect (head (queue 1)) 1) 8 | (check-error (head (empty Integer)) "head: given queue is empty") 9 | (check-expect (head (queue 1 2)) 1) 10 | (check-expect (head (queue 10 2 34 55)) 10) 11 | 12 | (check-expect (queue->list (tail (queue 1))) null) 13 | (check-error (tail (empty Integer)) "tail: given queue is empty") 14 | (check-expect (queue->list (tail (queue 10 12))) (list 12)) 15 | (check-expect (queue->list (tail (queue 23 45 -6))) (list 45 -6)) 16 | (check-expect (queue->list (tail (queue 23 45 -6 15))) 17 | (list 45 -6 15)) 18 | 19 | (check-expect (queue->list (enqueue 10 (queue 23 45 -6 15))) 20 | (list 23 45 -6 15 10)) 21 | (check-expect (queue->list (enqueue 10 (empty Integer))) (list 10)) 22 | 23 | (check-expect (queue->list (enqueue 10 (queue 20))) 24 | (list 20 10)) 25 | 26 | (check-expect (queue->list (apply queue (build-list 100 (λ(x) x)))) 27 | (build-list 100 (λ(x) x))) 28 | 29 | (check-expect (queue->list (map + (queue 1 2 3 4 5) (queue 1 2 3 4 5))) 30 | (list 2 4 6 8 10)) 31 | 32 | (check-expect (queue->list (map - (queue 1 2 3 4 5) (queue 1 2 3 4 5))) 33 | (list 0 0 0 0 0)) 34 | 35 | (check-expect (fold + 0 (queue 1 2 3 4 5)) 15) 36 | 37 | 38 | (check-expect (queue->list (filter positive? (queue 1 2 -4 5 0 -6 12 3 -2))) 39 | (list 1 2 5 12 3)) 40 | 41 | (check-expect (queue->list (filter negative? (queue 1 2 -4 5 0 -6 12 3 -2))) 42 | (list -4 -6 -2)) 43 | 44 | (check-expect (queue->list (remove positive? (queue 1 2 -4 5 0 -6 12 3 -2))) 45 | (list -4 0 -6 -2)) 46 | 47 | (check-expect (queue->list (remove negative? (queue 1 2 -4 5 0 -6 12 3 -2))) 48 | (list 1 2 5 0 12 3)) 49 | (check-expect (fold + 0 (queue 1 2 3 4 5) (queue 1 2 3 4 5)) 30) 50 | (test) 51 | -------------------------------------------------------------------------------- /pfds/tests/redblacktrees-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/scheme 2 | 3 | (require pfds/red-black-tree) 4 | (require typed/test-engine/scheme-tests) 5 | 6 | ;; NOTE: 7 | ;; Rebalancing used in Okasaki version of Red Black Trees is slightly 8 | ;; different from that of popular version. 9 | ;; As a consequence of this difference, 10 | ;; - Okasaki version is easy to implement. 11 | ;; - There is a difference in ordering of elements. For example, in the 12 | ;; test below, popular version would give (list 2 3 4 1 5). Because 13 | ;; redblacktree->list takes the root element in the red-black tree and 14 | ;; populates it in a list and then deletes the root element. When it 15 | ;; deletes the root node, balancing is done, since the balancing differs 16 | ;; in Okasaki version, 4 becomes the root of the tree instead of 3 which 17 | ;; is the case in the popular version. 18 | 19 | (check-expect (redblacktree->list (redblacktree < 1 2 3 4 5)) 20 | (list 2 4 3 1 5)) 21 | (check-expect (root (redblacktree < 1 2 3 4 5 6 7)) 4) 22 | (check-expect (root (redblacktree < 1 2 3 4 5)) 2) 23 | (define lst (build-list 100 (λ: ([x : Integer]) x))) 24 | (check-expect ((inst sort Integer Integer) (redblacktree->list (apply redblacktree < lst)) <) lst) 25 | (check-expect (root (delete 2 (redblacktree < 1 2 3 4 5))) 4) 26 | (check-expect (root (delete-root (redblacktree < 1 2 3 4 5))) 4) 27 | (check-expect (member? 5 (redblacktree < 1 2 3 4 5)) #t) 28 | (check-expect (member? 5 (redblacktree > 1 2 3 4 5)) #t) 29 | (check-expect (member? 50 (redblacktree > 1 2 3 4 5)) #f) 30 | (check-expect (member? 50 (redblacktree < 1 2 3 4 5)) #f) 31 | (check-expect (member? 1 (redblacktree > 1 2 3 4 5)) #t) 32 | (check-expect (member? 2 (redblacktree > 1 2 3 4 5)) #t) 33 | (check-expect (member? 95 (apply redblacktree < lst)) #t) 34 | (check-expect (empty? (delete-root (redblacktree < 1))) #t) 35 | (check-expect (empty? (redblacktree < 1)) #f) 36 | 37 | (check-error (root (delete-root (redblacktree < 1))) 38 | "root: given tree is empty") 39 | (check-error (delete 1 (delete-root (redblacktree < 1))) 40 | "delete: given key not found in the tree") 41 | 42 | (check-error (delete-root (delete-root (redblacktree < 1))) 43 | "delete-root: given tree is empty") 44 | (test) 45 | -------------------------------------------------------------------------------- /pfds/tests/skewbinaryrandomaccesslist-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require (prefix-in sh: scheme/base)) 3 | (require pfds/ralist/skew) 4 | (require typed/test-engine/scheme-tests) 5 | 6 | (check-expect (empty? empty) #t) 7 | (check-expect (empty? (list 1 2 3)) #f) 8 | (check-expect (head (list 1 2 3)) 1) 9 | (check-expect (head (list 2 3)) 2) 10 | (check-error (head null) "head: given list is empty") 11 | 12 | (check-expect (->list (tail (list 1 2 3))) (sh:list 2 3)) 13 | (check-expect (->list (tail (list 2 3))) (sh:list 3)) 14 | (check-expect (->list (tail (list 3))) null) 15 | (check-error (tail null) "tail: given list is empty") 16 | 17 | (check-expect (->list (cons 5 (list 1 2 3))) 18 | (sh:list 5 1 2 3)) 19 | (check-expect (->list (cons 10 (list 2 3))) 20 | (sh:list 10 2 3)) 21 | (check-expect (->list (cons 12 (list 3))) 22 | (sh:list 12 3)) 23 | (check-expect (->list (cons 12 null)) 24 | (sh:list 12)) 25 | 26 | (check-expect (->list (list-set (list 1 2 3) 2 5)) 27 | (sh:list 1 2 5)) 28 | (check-expect (->list (list-set (list 1 2 3 5 6) 4 10)) 29 | (sh:list 1 2 3 5 10)) 30 | (check-error (list-set (list 1 2 3 5) 4 10) 31 | "list-set: given index out of bounds") 32 | (check-error (list-set null 0 10) 33 | "list-set: given index out of bounds") 34 | (check-error (list-set null -1 10) 35 | "list-set: given index out of bounds") 36 | 37 | (check-expect (list-ref (list 1 2 3) 2) 3) 38 | (check-expect (list-ref (list 1 2 3) 0) 1) 39 | (check-expect (list-ref (list 1 2 3) 1) 2) 40 | (check-error (list-ref (list 1 2 3 5) 4) 41 | "list-ref: given index out of bounds") 42 | (check-error (list-ref null 0) 43 | "list-ref: given index out of bounds") 44 | (check-error (list-ref null -1) 45 | "list-ref: given index out of bounds") 46 | 47 | (check-expect (->list (drop 2 (list 1 2 3))) 48 | (sh:list 3)) 49 | (check-expect (->list (drop 5 (list 1 2 3 5 6))) 50 | (sh:list)) 51 | (check-expect (->list (drop 3 (list 1 2 3 5 6))) 52 | (sh:list 5 6)) 53 | (check-expect (drop 0 null) null) 54 | (check-error (drop 5 (list 1 2 3 5)) 55 | "drop: not enough elements to drop") 56 | (check-error (drop -1 null) 57 | "drop: not enough elements to drop") 58 | 59 | (define lst (build-list 100 (λ: ([x : Integer]) x))) 60 | (check-expect (->list (apply list lst)) lst) 61 | 62 | (check-expect (length (list 1 2 3)) 3) 63 | (check-expect (length (list 1 2 3 10 12)) 5) 64 | (check-expect (length null) 0) 65 | 66 | (check-expect (->list (map + (list 1 2 3 4 5) (list 1 2 3 4 5))) 67 | (sh:list 2 4 6 8 10)) 68 | 69 | (check-expect (->list (map - (list 1 2 3 4 5) (list 1 2 3 4 5))) 70 | (sh:list 0 0 0 0 0)) 71 | 72 | (check-expect (foldl + 0 (list 1 2 3 4 5)) 15) 73 | 74 | (check-expect (foldl - 2 (list 1 2 3 4 5)) -13) 75 | 76 | (check-expect (foldr + 0 (list 1 2 3 4 5)) 15) 77 | 78 | (check-expect (foldr + 0 (list 1 2 3 4 5) (list 1 2 3 4 5)) 30) 79 | 80 | (check-expect (->list (filter positive? (list 1 2 -4 5 0 -6 12 3 -2))) 81 | (sh:list 1 2 5 12 3)) 82 | 83 | (check-expect (->list (filter negative? (list 1 2 -4 5 0 -6 12 3 -2))) 84 | (sh:list -4 -6 -2)) 85 | 86 | (check-expect (->list (remove positive? (list 1 2 -4 5 0 -6 12 3 -2))) 87 | (sh:list -4 0 -6 -2)) 88 | 89 | (check-expect (->list (remove negative? (list 1 2 -4 5 0 -6 12 3 -2))) 90 | (sh:list 1 2 5 0 12 3)) 91 | 92 | (test) 93 | -------------------------------------------------------------------------------- /pfds/tests/skewbinomialheap-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require pfds/heap/skew-binomial) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | 6 | (: less-than? : (Integer Integer -> Boolean)) 7 | (define (less-than? a b) 8 | (<= a b)) 9 | 10 | (: gt : (Integer Integer -> Boolean)) 11 | (define (gt a b) 12 | (> a b)) 13 | 14 | (: str-less-than? : (String String -> Boolean)) 15 | (define (str-less-than? a b) 16 | (string<=? a b)) 17 | 18 | (check-expect (find-min/max (heap less-than? 1 2 3 4)) 1) 19 | (check-expect (find-min/max (heap less-than? 1 2 3 0)) 0) 20 | (check-expect (find-min/max (heap less-than? 1 2 -3 4)) -3) 21 | (check-error (find-min/max (delete-min/max (heap less-than? 1))) 22 | "find-min/max: given heap is empty") 23 | 24 | (check-expect (sorted-list (delete-min/max 25 | (heap less-than? 1 2 3 4))) 26 | (list 2 3 4)) 27 | (check-expect (sorted-list (delete-min/max 28 | (heap less-than? 1 2 3 0))) 29 | (list 1 2 3)) 30 | (check-expect (sorted-list (delete-min/max 31 | (heap less-than? 1 2 -3 4))) 32 | (list 1 2 4)) 33 | (check-error (delete-min/max (delete-min/max 34 | (heap less-than? 1))) 35 | "delete-min/max: given heap is empty") 36 | 37 | (check-expect (sorted-list (delete-min/max 38 | (heap less-than? 1))) (list)) 39 | (check-expect (sorted-list (delete-min/max 40 | (heap less-than? 1 -2 -3 -4))) 41 | (list -3 -2 1)) 42 | 43 | (check-expect (sorted-list (insert 10 (ann (heap less-than? 1 -2 -3 -4) 44 | (Heap Integer)))) 45 | (list -4 -3 -2 1 10)) 46 | 47 | (check-expect (sorted-list (insert -10 (heap less-than? 1 20 -3 -4))) 48 | (list -10 -4 -3 1 20)) 49 | 50 | (check-expect (sorted-list (insert 5 (heap less-than? 1 2 -3 -4))) 51 | (list -4 -3 1 2 5)) 52 | 53 | (check-expect (sorted-list (merge (ann (heap less-than? 2 3 -10) 54 | (Heap Integer)) 55 | (ann (heap less-than? 1 -2 -3 -4) 56 | (Heap Integer)))) 57 | (list -10 -4 -3 -2 1 2 3)) 58 | 59 | (check-expect (sorted-list (merge (delete-min/max 60 | (ann (heap less-than? -1 5) 61 | (Heap Integer))) 62 | (ann (heap less-than? 1 -2 -3 -4) 63 | (Heap Integer)))) 64 | (list -4 -3 -2 1 5)) 65 | 66 | (check-expect (sorted-list (merge (ann (heap less-than? 1 -2 -3 -4) 67 | (Heap Integer)) 68 | (delete-min/max 69 | (ann (heap less-than? -1 5) 70 | (Heap Integer))))) 71 | (list -4 -3 -2 1 5)) 72 | 73 | (define int-list (build-list 100 (λ: ([x : Integer]) x))) 74 | 75 | (check-expect (sorted-list (apply heap less-than? int-list)) 76 | int-list) 77 | 78 | (check-expect (sorted-list (apply heap gt int-list)) 79 | (reverse int-list)) 80 | 81 | (define lst (build-list 100 (λ: ([x : Integer]) x))) 82 | (check-expect (sorted-list (apply heap less-than? lst)) lst) 83 | (check-expect (sorted-list (apply heap gt lst)) (reverse lst)) 84 | 85 | (check-expect (fold + 0 (heap < 1 1 1 10 1 15)) 29) 86 | (check-expect (sorted-list (map < add1 (heap < 10 4 5 14 29 15))) 87 | (list 5 6 11 15 16 30)) 88 | (check-expect (fold + 0 (heap > 1)) 1) 89 | (check-expect (sorted-list (filter even? (heap < 10 4 5 14 29 15))) 90 | (list 4 10 14)) 91 | (check-expect (sorted-list (remove odd? (heap < 10 4 5 14 29 15))) 92 | (list 4 10 14)) 93 | (check-expect (sorted-list (remove even? (heap < 10 4 5 14 29 15))) 94 | (list 5 15 29)) 95 | (check-expect (sorted-list (filter odd? (heap < 10 4 5 14 29 15))) 96 | (list 5 15 29)) 97 | 98 | (check-expect (ormap odd? (heap < 10 4 5 14 29 15)) #t) 99 | (check-expect (ormap even? (heap < 5 29 15)) #f) 100 | (check-expect (andmap odd? (heap < 5 29 15)) #t) 101 | (check-expect (andmap odd? (heap < 5 29 14)) #f) 102 | (test) 103 | -------------------------------------------------------------------------------- /pfds/tests/splayheap-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require pfds/heap/splay) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | 6 | (: less-than? : (Integer Integer -> Boolean)) 7 | (define (less-than? a b) 8 | (<= a b)) 9 | 10 | (: gt : (Integer Integer -> Boolean)) 11 | (define (gt a b) 12 | (> a b)) 13 | 14 | (: str-less-than? : (String String -> Boolean)) 15 | (define (str-less-than? a b) 16 | (string<=? a b)) 17 | 18 | (check-expect (find-min/max (heap less-than? 1 2 3 4)) 1) 19 | (check-expect (find-min/max (heap less-than? 1 2 3 0)) 0) 20 | (check-expect (find-min/max (heap less-than? 1 2 -3 4)) -3) 21 | (check-error (find-min/max (delete-min/max (heap less-than? 1))) 22 | "find-min/max: given heap is empty") 23 | 24 | (check-expect (sorted-list (delete-min/max (heap less-than? 1 2 3 4))) 25 | (list 2 3 4)) 26 | (check-expect (sorted-list (delete-min/max (heap less-than? 1 2 3 0))) 27 | (list 1 2 3)) 28 | (check-expect (sorted-list (delete-min/max (heap less-than? 1 2 -3 4))) 29 | (list 1 2 4)) 30 | (check-error (delete-min/max (delete-min/max (heap less-than? 1))) 31 | "delete-min/max: given heap is empty") 32 | 33 | (check-expect (sorted-list (delete-min/max (heap less-than? 1))) (list)) 34 | (check-expect (sorted-list (delete-min/max (heap less-than? 1 -2 -3 -4))) 35 | (list -3 -2 1)) 36 | 37 | (check-expect (sorted-list (insert 10 (ann (heap less-than? 1 -2 -3 -4) 38 | (Heap Integer)))) 39 | (list -4 -3 -2 1 10)) 40 | 41 | (check-expect (sorted-list (insert -10 (heap less-than? 1 20 -3 -4))) 42 | (list -10 -4 -3 1 20)) 43 | 44 | (check-expect (sorted-list (insert -1 (heap less-than? -3 -4))) 45 | (list -4 -3 -1)) 46 | 47 | (check-expect (sorted-list (merge (ann (heap less-than? 2 3 -10) 48 | (Heap Integer)) 49 | (ann (heap less-than? 1 -2 -3 -4) 50 | (Heap Integer)))) 51 | (list -10 -4 -3 -2 1 2 3)) 52 | 53 | (check-expect (sorted-list (merge (delete-min/max 54 | (ann (heap less-than? -1 5) 55 | (Heap Integer))) 56 | (ann (heap less-than? 1 -2 -3 -4) 57 | (Heap Integer)))) 58 | (list -4 -3 -2 1 5)) 59 | 60 | (check-expect (sorted-list (merge (ann (heap less-than? 1 -2 -3 -4) 61 | (Heap Integer)) 62 | (delete-min/max 63 | (ann (heap less-than? -1 5) 64 | (Heap Integer))))) 65 | (list -4 -3 -2 1 5)) 66 | 67 | (define int-list (build-list 100 (λ: ([x : Integer]) x))) 68 | 69 | (define int-list1 (build-list 100 (λ: ([x : Integer]) (+ 100 x)))) 70 | 71 | (check-expect (sorted-list (merge (apply heap less-than? int-list) 72 | (apply heap less-than? int-list1))) 73 | (append int-list int-list1)) 74 | 75 | (check-expect (sorted-list (apply heap less-than? int-list)) 76 | int-list) 77 | 78 | (check-expect (sorted-list (apply heap gt int-list)) 79 | (reverse int-list)) 80 | (check-expect (empty? (heap gt 1 2 3 4)) #f) 81 | 82 | (check-expect (empty? (heap gt)) #t) 83 | 84 | (check-expect (fold + 0 (heap < 1 1 1 10 1 15)) 29) 85 | (check-expect (sorted-list (map < add1 (heap < 10 4 5 14 29 15))) 86 | (list 5 6 11 15 16 30)) 87 | (check-expect (fold + 0 (heap > 1)) 1) 88 | (check-expect (sorted-list (filter even? (heap < 10 4 5 14 29 15))) 89 | (list 4 10 14)) 90 | (check-expect (sorted-list (remove odd? (heap < 10 4 5 14 29 15))) 91 | (list 4 10 14)) 92 | (check-expect (sorted-list (remove even? (heap < 10 4 5 14 29 15))) 93 | (list 5 15 29)) 94 | (check-expect (sorted-list (filter odd? (heap < 10 4 5 14 29 15))) 95 | (list 5 15 29)) 96 | 97 | (check-expect (ormap odd? (heap < 10 4 5 14 29 15)) #t) 98 | (check-expect (ormap even? (heap < 5 29 15)) #f) 99 | (check-expect (andmap odd? (heap < 5 29 15)) #t) 100 | (check-expect (andmap odd? (heap < 5 29 14)) #f) 101 | 102 | (test) 103 | -------------------------------------------------------------------------------- /pfds/tests/stream-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require pfds/stream) 3 | (require typed/test-engine/scheme-tests) 4 | 5 | (check-expect (empty-stream? empty-stream) #t) 6 | (check-expect (empty-stream? (stream 1)) #f) 7 | (check-expect (empty-stream? (stream 1 2 3)) #f) 8 | 9 | (check-expect (stream-car (stream 1)) 1) 10 | (check-expect (stream-car (stream 2 3 1)) 2) 11 | (check-error (stream-car empty-stream) "stream-car: given stream is empty") 12 | 13 | (check-expect (stream->list (stream-cdr (stream 1))) null) 14 | (check-expect (stream->list (stream-cdr (stream 2 3 1))) (list 3 1)) 15 | (check-error (stream-cdr empty-stream) "stream-cdr: given stream is empty") 16 | 17 | (define lst1 (build-list 100 (λ: ([x : Integer]) x))) 18 | (define lst2 (build-list 100 (λ: ([x : Integer]) (+ x 100)))) 19 | (define lst3 (build-list 90 (λ: ([x : Integer]) (+ x 10)))) 20 | 21 | (check-expect (stream->list (stream-cdr (apply stream lst1))) 22 | (cdr lst1)) 23 | 24 | (check-expect (stream->list (stream-append (apply stream lst1) 25 | (apply stream lst2))) 26 | (append lst1 lst2)) 27 | 28 | (check-expect (stream->list (stream-reverse (apply stream lst1))) 29 | (reverse lst1)) 30 | 31 | (check-expect (stream->list (drop 10 (apply stream lst1))) 32 | lst3) 33 | 34 | (check-expect (stream->list (drop 0 (apply stream lst1))) 35 | lst1) 36 | 37 | (check-expect (stream->list (drop 1 (apply stream lst1))) 38 | (cdr lst1)) 39 | 40 | (check-expect (stream->list (drop 50 (apply stream lst1))) 41 | (build-list 50 (λ: ([x : Integer]) (+ x 50)))) 42 | 43 | (check-expect (stream->list (take 0 (apply stream lst1))) 44 | null) 45 | 46 | (check-error (stream->list (take 10 (stream 1 2 3 4))) 47 | "take: not enough elements to take") 48 | 49 | (check-error (stream->list (drop 10 (stream 1 2 3 4))) 50 | "drop: not enough elements to drop") 51 | 52 | (check-expect (stream->list (take 10 (apply stream lst1))) 53 | (list 0 1 2 3 4 5 6 7 8 9)) 54 | 55 | (check-expect (stream->list (take 5 (apply stream lst1))) 56 | (list 0 1 2 3 4)) 57 | 58 | (check-expect (stream->list (take 90 (apply stream lst1))) 59 | (build-list 90 (λ: ([x : Integer]) x))) 60 | 61 | (test) 62 | -------------------------------------------------------------------------------- /pfds/tests/tests-main.rkt: -------------------------------------------------------------------------------- 1 | #lang typed-scheme 2 | (require "bankers-deque-tests.rkt" 3 | "bankers-queue-tests.rkt" 4 | "binary-ran-access-list-tests.rkt" 5 | "binomialheap-tests.rkt" 6 | "bootstrapedheap-tests.rkt" 7 | "bootstrapedqueue-tests.rkt" 8 | "catenablelist-tests.rkt" 9 | "hood-melville-queue-tests.rkt" 10 | "implicitdeque-tests.rkt" 11 | "implicitqueue-tests.rkt" 12 | "lazypairingheap-test.rkt" 13 | "leftistheaps-tests.rkt" 14 | "pairingheap-test.rkt" 15 | "physicists-queue-tests.rkt" 16 | "realtimedeque-tests.rkt" 17 | "realtimequeue-tests.rkt" 18 | "redblacktrees-tests.rkt" 19 | "skewbinaryrandomaccesslist-tests.rkt" 20 | "skewbinomialheap-tests.rkt" 21 | "splayheap-tests.rkt" 22 | "stream-tests.rkt" 23 | "tries-test.rkt" 24 | "vlist-tests.rkt") 25 | -------------------------------------------------------------------------------- /pfds/tests/treap-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | (require pfds/treap) 3 | (require typed/test-engine/racket-tests) 4 | 5 | (: str-less-than? : (String String -> Boolean)) 6 | (define (str-less-than? a b) 7 | (string<=? a b)) 8 | 9 | (check-expect (find-min/max (treap < 1 2 3 4)) 1) 10 | (check-expect (find-min/max (treap < 1 2 3 0)) 0) 11 | (check-expect (find-min/max (treap < 1 2 -3 4)) -3) 12 | (check-error (find-min/max (delete-min/max (treap < 1))) 13 | "find-min/max: given treap is empty") 14 | 15 | (check-expect ((inst sort Integer Integer) 16 | (treap->list (delete-min/max (treap <= 1 2 3 4))) <) 17 | (list 2 3 4)) 18 | (check-expect ((inst sort Integer Integer) 19 | (treap->list (delete-min/max (treap <= 1 2 3 0))) <) 20 | (list 1 2 3)) 21 | (check-expect ((inst sort Integer Integer) 22 | (treap->list (delete-min/max (treap <= 1 2 -3 4))) <) 23 | (list 1 2 4)) 24 | (check-error (delete-min/max (delete-min/max (treap <= 1))) 25 | "delete-min/max: given treap is empty") 26 | 27 | (check-expect (treap->list (delete-min/max (treap <= 1))) (list)) 28 | (check-expect ((inst sort Integer Integer) 29 | (treap->list (delete-min/max (treap <= 1 -2 -3 -4))) <) 30 | (list -3 -2 1)) 31 | 32 | (check-expect ((inst sort Integer Integer) 33 | (treap->list ((inst insert Integer) 10 (treap <= 1 -2 -3 -4))) <) 34 | (list -4 -3 -2 1 10)) 35 | 36 | (check-expect ((inst sort Integer Integer) 37 | (treap->list (insert -10 (treap <= 1 20 -3 -4))) <) 38 | (list -10 -4 -3 1 20)) 39 | 40 | (check-expect ((inst sort Integer Integer) 41 | (treap->list (insert -1 (treap <= -3 -4))) <) 42 | (list -4 -3 -1)) 43 | 44 | ;;(check-expect (treap->list (merge (treap <= 2 3 -10) 45 | ;; (treap <= 1 -2 -3 -4))) 46 | ;; (list -10 -4 -3 -2 1 2 3)) 47 | ;; 48 | ;;(check-expect (treap->list (merge (delete-min/max (treap <= -1 5)) 49 | ;; (treap <= 1 -2 -3 -4))) 50 | ;; (list -4 -3 -2 1 5)) 51 | ;; 52 | ;;(check-expect (treap->list (merge (treap <= 1 -2 -3 -4) 53 | ;; (delete-min/max (treap <= -1 5)))) 54 | ;; (list -4 -3 -2 1 5)) 55 | 56 | (define int-list (build-list 100 (λ: ([x : Integer]) x))) 57 | 58 | (define int-list1 (build-list 100 (λ: ([x : Integer]) (+ 100 x)))) 59 | 60 | ;(check-expect (treap->list (merge (apply treap <= int-list) 61 | ; (apply treap <= int-list1))) 62 | ; (append int-list int-list1)) 63 | 64 | (check-expect ((inst sort Integer Integer) 65 | (treap->list (apply treap <= int-list)) <) 66 | int-list) 67 | 68 | (check-expect ((inst sort Integer Integer) 69 | (treap->list (apply treap > int-list)) >) 70 | (reverse int-list)) 71 | (check-expect (empty? (treap > 1 2 3 4)) #f) 72 | 73 | (check-expect (empty? (treap >)) #t) 74 | 75 | (check-expect (fold + 0 (treap < 1 1 1 10 1 15)) 29) 76 | (check-expect ((inst sort Integer Integer) 77 | (treap->list (map < add1 (treap < 10 4 5 14 29 15))) <) 78 | (list 5 6 11 15 16 30)) 79 | (check-expect (fold + 0 (treap > 1)) 1) 80 | (check-expect ((inst sort Integer Integer) 81 | (treap->list (filter even? (treap < 10 4 5 14 29 15))) <) 82 | (list 4 10 14)) 83 | (check-expect ((inst sort Integer Integer) 84 | (treap->list (remove odd? (treap < 10 4 5 14 29 15))) <) 85 | (list 4 10 14)) 86 | (check-expect ((inst sort Integer Integer) 87 | (treap->list (remove even? (treap < 10 4 5 14 29 15))) <) 88 | (list 5 15 29)) 89 | (check-expect ((inst sort Integer Integer) 90 | (treap->list (filter odd? (treap < 10 4 5 14 29 15))) <) 91 | (list 5 15 29)) 92 | 93 | (check-expect (ormap odd? (treap < 10 4 5 14 29 15)) #t) 94 | (check-expect (ormap even? (treap < 5 29 15)) #f) 95 | (check-expect (andmap odd? (treap < 5 29 15)) #t) 96 | (check-expect (andmap odd? (treap < 5 29 14)) #f) 97 | 98 | ;;; contains? 99 | (check-expect (contains? 'x ((inst treap Symbol) symbollist "Hari") 7 | (bind (string->list "JP") 5 8 | (trie 9 | (map string->list 10 | (list "Hari Prashanth" "Hari" "Hari " "K R H P"))))) 11 | 2) 12 | 13 | (check-expect 14 | (lookup (string->list "Hari") 15 | (tries 16 | (list 1 2 3 4 5) 17 | (map string->list (list "Hari" "Prashanth" "K R" "KRHP" "K R H P")))) 18 | 1) 19 | 20 | (check-expect 21 | (lookup (string->list "Prashanth") 22 | (tries 23 | (list 1 2 3 4 5) 24 | (map string->list (list "Hari" "Prashanth" "K R" "KRHP" "K R H P")))) 25 | 2) 26 | 27 | (check-expect 28 | (lookup (string->list "KRHP") 29 | (tries 30 | (list 1 2 3 4 5) 31 | (map string->list (list "Hari" "Prashanth" "K R" "KRHP" "K R H P")))) 32 | 4) 33 | 34 | (check-expect 35 | (lookup (string->list "K R H P") 36 | (tries 37 | (list 1 2 3 4 5) 38 | (map string->list (list "Hari" "Prashanth" "K R" "KRHP" "K R H P")))) 39 | 5) 40 | 41 | (check-expect 42 | (lookup (string->list "K R") 43 | (tries 44 | (list 1 2 3 4 5) 45 | (map string->list (list "Hari" "Prashanth" "K R" "KRHP" "K R H P")))) 46 | 3) 47 | 48 | (check-expect 49 | (lookup (string->list "Hari Prashanth") 50 | (tries 51 | (list 1 2 3 4) 52 | (map string->list (list "Hari Prashanth" "K R" "KRHP" "K R H P")))) 53 | 1) 54 | 55 | (check-expect 56 | (lookup (string->list "Hari ") 57 | (tries 58 | (list 1 2 3 4) 59 | (map string->list (list "Hari Prashanth" "Hari" "Hari " "K R H P")))) 60 | 3) 61 | 62 | 63 | (check-expect 64 | (lookup (string->list "HariKRH") 65 | (bind (string->list "HariKRH") 5 66 | (tries 67 | (list 1 2 3 4) 68 | (map string->list 69 | (list "Hari Prashanth" "Hari" "Hari " "K R H P"))))) 70 | 5) 71 | 72 | (check-expect 73 | (lookup (string->list "JP") 74 | (bind (string->list "JP") 5 75 | (tries 76 | (list 1 2 3 4) 77 | (map string->list 78 | (list "Hari Prashanth" "Hari" "Hari " "K R H P"))))) 79 | 5) 80 | 81 | (check-error 82 | (lookup (string->list "Hari123") 83 | (bind (string->list "JP") 5 84 | (tries 85 | (list 1 2 3 4) 86 | (map string->list 87 | (list "Hari Prashanth" "Hari" "Hari " "K R H P"))))) 88 | "lookup: given key not found in the trie") 89 | 90 | (check-error 91 | (lookup (string->list "Har") 92 | (bind (string->list "JP") 5 93 | (tries 94 | (list 1 2 3 4) 95 | (map string->list 96 | (list "Hari Prashanth" "Hari" "Hari " "K R H P"))))) 97 | "lookup: given key not found in the trie") 98 | 99 | (test) 100 | -------------------------------------------------------------------------------- /pfds/tests/vlist-tests.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | (require (rename-in pfds/vlist 4 | [map vmap] 5 | [reverse vreverse] 6 | [length size] 7 | [foldr vfoldr] 8 | [foldl vfoldl] 9 | [filter vfilter] 10 | [list-ref get]) 11 | (prefix-in rk: racket/base)) 12 | 13 | (require typed/test-engine/scheme-tests) 14 | 15 | (define lst (rk:build-list 100 (λ:([x : Integer]) x))) 16 | 17 | (define vlst (apply list lst)) 18 | 19 | (check-expect (->list vlst) lst) 20 | 21 | (check-expect (->list (vmap add1 vlst)) 22 | (map add1 lst)) 23 | 24 | (check-expect (vfoldl + 0 vlst) (foldl + 0 lst)) 25 | 26 | (check-expect (vfoldl * 1 vlst) (foldl * 1 lst)) 27 | 28 | (check-expect (vfoldl + 0 vlst vlst) (foldl + 0 lst lst)) 29 | 30 | (check-expect (vfoldr + 0 vlst) (foldr + 0 lst)) 31 | 32 | (check-expect (vfoldr * 1 vlst) (foldr * 1 lst)) 33 | 34 | (check-expect (vfoldr + 0 vlst vlst) (foldr + 0 lst lst)) 35 | 36 | (check-expect (->list (vfilter (λ:([x : Integer]) (> x 50)) vlst)) 37 | (filter (λ:([x : Integer]) (> x 50)) lst)) 38 | 39 | (check-expect (->list (vreverse vlst)) (reverse lst)) 40 | 41 | (check-expect (get vlst (sub1 (size vlst))) (last vlst)) 42 | 43 | (check-expect (get vlst 0) (first vlst)) 44 | 45 | (check-error (get vlst (+ 5 (size vlst))) "list-ref: given index out of bounds") 46 | 47 | (check-expect (->list (rest vlst)) (cdr lst)) 48 | 49 | (check-error (first empty) "first: given vlist is empty") 50 | 51 | (check-error (last empty) "last: given vlist is empty") 52 | 53 | (check-error (rest empty) "rest: given vlist is empty") 54 | 55 | (check-expect (size empty) 0) 56 | 57 | (check-expect (size vlst) (length lst)) 58 | 59 | (check-expect (empty? empty) #t) 60 | 61 | (check-expect (empty? vlst) #f) 62 | 63 | (test) 64 | -------------------------------------------------------------------------------- /pfds/trie.rkt: -------------------------------------------------------------------------------- 1 | #lang typed/racket 2 | 3 | (provide lookup bind trie insert Trie tries) 4 | 5 | (require scheme/match) 6 | (define-type-alias (Key A) (Listof A)) 7 | 8 | (define-struct: Mt ()) 9 | (define-struct: (A) Some ([elem : A])) 10 | 11 | (define-type-alias (Option A) (U Mt (Some A))) 12 | 13 | (define-struct: (K V) Trie ([opt : (Option V)] 14 | [map : (Immutable-HashTable K (Trie K V))])) 15 | 16 | (: empty : (All (K V) (-> (Trie K V)))) 17 | (define (empty) 18 | (make-Trie (make-Mt) 19 | (ann (make-immutable-hash null) (Immutable-HashTable K (Trie K V))))) 20 | 21 | (: lookup : (All (K V) ((Key K) (Trie K V) -> V))) 22 | (define (lookup keys map) 23 | (if (null? keys) 24 | (let ([opt (Trie-opt map)]) 25 | (if (Mt? opt) 26 | (error 'lookup "given key not found in the trie") 27 | (Some-elem opt))) 28 | (let ([fst (car keys)] 29 | [hash (Trie-map map)]) 30 | (with-handlers 31 | ([exn:fail? (lambda (error?) 32 | (error 'lookup "given key not found in the trie"))]) 33 | (lookup (cdr keys) (hash-ref hash fst)))))) 34 | 35 | (: bind : (All (K V) ((Key K) V (Trie K V) -> (Trie K V)))) 36 | (define (bind lok v map) 37 | (let ([hash (Trie-map map)] 38 | [fst (car lok)] 39 | [rst (cdr lok)] 40 | [opt (Trie-opt map)]) 41 | (make-Trie opt (hash-set hash fst 42 | (ann (with-handlers 43 | ([exn:fail? 44 | (lambda (error?) (build v rst))]) 45 | (bind rst v (hash-ref hash fst))) 46 | (Trie K V)))))) 47 | 48 | (: build : (All (K V) (V (Listof K) -> (Trie K V)))) 49 | (define (build val lstk) 50 | (if (null? lstk) 51 | (make-Trie (make-Some val) 52 | (ann (make-immutable-hash null) 53 | (Immutable-HashTable K (Trie K V)))) 54 | (make-Trie (make-Mt) 55 | (make-immutable-hash 56 | (list (cons (car lstk) (build val (cdr lstk)))))))) 57 | 58 | (: trie : (All (K) ((Listof (Listof K)) -> (Trie K Integer)))) 59 | (define (trie lst) 60 | (insert (get-vals lst) lst (ann (empty) (Trie K Integer)))) 61 | 62 | (: get-vals : (All (K) ((Listof (Listof K)) -> (Listof Integer)))) 63 | (define (get-vals lst) 64 | (: local : (All (K) (Integer (Listof (Listof K)) -> (Listof Integer)))) 65 | (define (local ctr lstk) 66 | (if (null? (cdr lstk)) 67 | (cons ctr null) 68 | (cons ctr (local (add1 ctr) (cdr lstk))))) 69 | (local 1 lst)) 70 | 71 | ;; While creating the tree, 72 | ;; if (hash-ref hash k) throws an error, 73 | ;; then it means that that there is no entry for k. So build a new 74 | ;; Trie for rest of the key and create an entry for k. 75 | ;; else go deeper into the insert searching for the rest of the key. 76 | 77 | (: insert : 78 | (All (K V) ((Listof V) (Listof (Listof K)) (Trie K V) -> (Trie K V)))) 79 | (define (insert lstv lstk tri) 80 | (match (list lstv lstk) 81 | [(list null null) tri] 82 | [(list (cons v vs) (cons (cons k ks) rstk)) 83 | (let* ([hash (Trie-map tri)] 84 | [tree (ann (with-handlers ([exn:fail? (lambda (error?) 85 | (build v ks))]) 86 | (go-deep (hash-ref hash k) ks v)) 87 | (Trie K V))]) 88 | (insert vs rstk 89 | (make-Trie (Trie-opt tri) (hash-set hash k tree))))])) 90 | 91 | (: tries : (All (K V) ((Listof V) (Listof (Listof K)) -> (Trie K V)))) 92 | (define (tries lstv lstk) 93 | (insert lstv lstk (ann (empty) (Trie K V)))) 94 | 95 | ;; Uses the same trick as previous one does 96 | (: go-deep : (All (K V) ((Trie K V) (Listof K) V -> (Trie K V)))) 97 | (define (go-deep tri lstk val) 98 | (if (null? lstk) 99 | (make-Trie (make-Some val) (Trie-map tri)) 100 | (let* ([hash (Trie-map tri)] 101 | [k (car lstk)] 102 | [ks (cdr lstk)] 103 | [insert (ann (with-handlers 104 | ([exn:fail? (lambda (error?) (build val ks))]) 105 | (go-deep (hash-ref hash k) ks val)) 106 | (Trie K V))]) 107 | (make-Trie (Trie-opt tri) (hash-set hash k insert))))) 108 | --------------------------------------------------------------------------------