1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
|
(in-package #:containers)
#|
;;; stack with a list
(defclass* stack-using-list (abstract-stack contents-as-list-mixin)
((contents
:initform nil
:accessor contents
)))
(defmethod first-item ((container abstract-stack))
(first (contents container)))
(defmethod pop-item ((stack stack-using-list))
(pop (contents stack)))
;;; bag-list
(defclass* bag-list (bag-container-abstract contents-as-list-mixin)
())
(defmethod delete-item ((container bag-list) item)
(setf (contents container)
(delete item (contents container)))
item)
;;; bag-hash
(defclass* bag-hash (bag-container-abstract contents-as-hashtable-mixin)
())
(defmethod delete-item ((container bag-hash) item)
(remhash item (contents container))
item)
(defmethod insert-item ((container contents-as-hashtable-mixin) item)
(setf (gethash item (contents container)) item))
(defgeneric smallest-item (sorted-container-mixin))
(defgeneric biggest-item (sorted-container-mixin))
|#
#|
Container Notes
u::abstract-container
make-container
size
empty-p
empty-container
u::bounded-container-mixin
total-size
u::indexed-container-mixin (and associative-container-mixin)
item-at
item-at!
u::iteratable-container-mixin
iterate-container
collect-elements (basic version using iterate-container)
? search-for-item (container item :key :test)
? first-match (container :key :test)
u::findable-container-mixin
;;?? Needs key and test
find-item (findable-container-mixin item)
u::ordered-container-mixin
(defgeneric first-item (ordered-container-mixin))
(defgeneric item-after (ordered-container-mixin item))
(defgeneric item-before (ordered-container-mixin item))
(defgeneric last-item (ordered-container-mixin))
insert-item
insert-sequence
insert-list
u::sorted-container-mixin
(defgeneric successor (sorted-container-mixin item))
(defgeneric predecessor (sorted-container-mixin item))
u::contents-as-hashtable-mixin
collect-keys
iterate-key-value
u::abstract-queue
dequeue
enqueue == insert-item
u::abstract-stack
first-item (settable)
pop-item
push-item
test (in bst, make part of searchable; make keyed part of searchable?)
height (of a tree)
delete-item
delete-item-if
iterate-key-value doesn't make sense for nested hash-tables, we
should implement both
nested and non-nested...
get rid of empty, make everyone type empty-container or, better yet, empty!
aided and unaided searching... I can search any iteratable container
but I can search
bst's fast.
maybe find-item and search-for-item (the slower and more flexible
one) hunt-for-item, lookup-item vs find-item
? append-item
? delete-last
|#
#|
Todo
----
* Re-design class hierarchy
* queue-on-container
* create heap class and hide EKSL heap in it, then use this for heap based PQ
* sets and bags need :test, :key in the constructor
* the X-container adaptors have very similar implementation, make
this a sub-class (adaptive-container-mixin)
to handle most of the pattern.
* sparse-array should use associative-container (nested hash tables)
and be able
to iterate container
* arrays should allow for initial-contents
* add associative-arrays
* add initial-element-fn
* sparse-array-container should use contents-as-hashtable-mixin (and
have size the amount in use?)
* restore regular associative-container and created
nested-associative-container
* doubly-linked-list
* add methods for working with the end of an ordered-container (and a
new class)
* break ordered container into pieces corresponding to efficiency classes
* delete-first, delete-last, append-item and so on
* generic operations for standard lisp types? (container ops are
destructive... makes this hard)
** fix / improve bags and add sets
** we should have stack-container and bag-container and so on.
** remove smallest-item and biggest-item (replace with first-item and
last-item)
** dump generic-iteratable-container-mixin
* rework observable stuff and add to eksl-utilities
* copy-container
* samep (good use of forward-iterators)
* generic algoritms (e.g., sort, merge, find...)??
* instead of insert-list, insert-sequence, and so on... have
insert-object and dispatch on it
More esoteric data structures
Fibonacci heaps (and other heaps)
etc.
Less esoteric data structures
??
bag-container / set-container using lists, hash-tables or other
things. The problem
is that the bag/set-container seens to require specialization on
bag/set. The other
problem is that a bag-container using a hash-table should implement a
fast find-item
rather than the iterative search-for-item.
|#
#|
Do we want to add assertions and such (use a parameter or a mixin)
Westy's slow-mixin
Look at various Lisp list operations (e.g., count, replace, and so on)
and see if they would make sense for any sorts of containers.
Setf's
|#
#|
From EKSL priority queue
Copy-queue
queue-length
priority-queue-head-or-nil ; = front unless queue is empty -> nil
priority-queue-delete
priority-queue-find
priority-queue-map-in-priority-order
priority-queue-map-in-heap-order
priority-queue-elements
print-priority-queue-elements
do-priority-queue
reorder-priority-queue))
#+Ignore
(defmacro declare-inline (function-names)
(dolist (name function-names)
`(declaim (inline ,name))))
(defmacro declaim-inline (function-name)
`(declaim (inline ,function-name)))
|#
(in-package #:u)
(defun test-container-class (container-class &rest args)
(let ((c (apply #'make-container container-class args)))
(test)
))
(defun container
))
(defun test-basic-container-operations (class)
(let ((c (make-container class)))
(insert-item c 1)
(insert-item c 2)
(insert-item c 3)
(ensure (= (size c) 3))
(empty! c)
(ensure (= (size c) 0))
(ensure (empty-p c))
(insert-list c '(2 3))
(ensure (= (size c) 2))))
(test-basic-container-operations 'dlist-container)
(test-basic-container-operations 'priority-queue-heap)
(mapc (lambda (c)
(print c)
(test-basic-container-operations c))
(DETERMINE-CONCRETE-CONTAINER-SUBCLASSES 'ordered-container-mixin))
(SET-CONTAINER BAG-CONTAINER STACK-CONTAINER PRIORITY-QUEUE-HEAP
DLIST-CONTAINER BASIC-QUEUE LIST-CONTAINER ALIST-CONTAINER
SPARSE-ARRAY-CONTAINER RING-BUFFER VECTOR-CONTAINER ARRAY-CONTAINER
ABSTRACT-FORCE-SIMULATOR-DOMAIN::FORCE-FLOW-GRID MBR HEAP-CONTAINER
BINARY-SEARCH-TREE RED-BLACK-TREE PRIORITY-QUEUE-ON-CONTAINER bag/set-container
ASSOCIATIVE-CONTAINER KEYED-ASSOCIATIVE-CONTAINER)
|#
#|
(setf a (make-container 'alist-container))
(setf (item-at a :a :b) 1
(item-at a :b :c) 2
(item-at a :c :d) 3
(item-at a :d :e) 4)
(delete-item-at a :a :b)
(iterate-key-value a (lambda (k v) (format t "~%~A ~A" k v)))
(iterate-keys a (lambda (k) (format t "~%~A" k)))
(setf a (make-container 'alist-container))
(setf (item-at a :a) 1
(item-at a :b) 2
(item-at a :c) 3
(item-at a :d) 4)
(delete-item-at a :a)
(iterate-key-value a (lambda (k v) (format t "~%~A ~A" k v)))
(iterate-keys a (lambda (k) (format t "~%~A" k)))
|#
#| Perhaps useful for documentation
(let ((c-1 (make-container 'associative-container))
(c-2 (make-container 'associative-container
:initial-element 2))
(c-3 (make-container 'associative-container
:initial-element (random 10)))
(c-4 (make-container 'associative-container
:initial-element-fn (lambda () (random 10)))))
(loop for c in (list c-1 c-2 c-3 c-4)
for name in (list "Basic Table" "Initial-element"
"Random Element" "Element Function") do
(format t "~%~%~A:" name)
(setf (item-at c :a) 1)
(format t "~%We get out what we put in.")
(format t "~%(item-at c :a) ==> ~A" (item-at c :a))
(format t "~%What do we get when we don't put anything in?")
(format t "~%(item-at c :b) ==> ~A" (item-at c :b))
(format t "~%We get the same thing each time ~
(even if we didn't add it ourselves).")
(format t "~%(item-at c :b) ==> ~A" (item-at c :b))
(format t "~%What happens if we look somewhere else? ~
(why initial-element-fn exists).")
(format t "~%(item-at c :c) ==> ~A" (item-at c :c))))
|#
|