| 1 |
(in-package :bos.m2) |
|---|
| 2 |
|
|---|
| 3 |
(enable-interpol-syntax) |
|---|
| 4 |
|
|---|
| 5 |
(defun escape-nl (string) |
|---|
| 6 |
(if string |
|---|
| 7 |
(regex-replace-all #?r"[\n\r]+" string #?"<br />") |
|---|
| 8 |
"")) |
|---|
| 9 |
|
|---|
| 10 |
(defun random-elt (choices) |
|---|
| 11 |
(when choices |
|---|
| 12 |
(elt choices (random (length choices))))) |
|---|
| 13 |
|
|---|
| 14 |
(defun topological-sort (objects constraints tie-breaker) |
|---|
| 15 |
;; copied from sb-kernel::topological-sort |
|---|
| 16 |
(declare (list objects constraints) |
|---|
| 17 |
(function tie-breaker)) |
|---|
| 18 |
(let ((obj-info (make-hash-table :size (length objects))) |
|---|
| 19 |
(free-objs nil) |
|---|
| 20 |
(result nil)) |
|---|
| 21 |
(dolist (constraint constraints) |
|---|
| 22 |
(let ((obj1 (car constraint)) |
|---|
| 23 |
(obj2 (cdr constraint))) |
|---|
| 24 |
(let ((info2 (gethash obj2 obj-info))) |
|---|
| 25 |
(if info2 |
|---|
| 26 |
(incf (first info2)) |
|---|
| 27 |
(setf (gethash obj2 obj-info) (list 1)))) |
|---|
| 28 |
(let ((info1 (gethash obj1 obj-info))) |
|---|
| 29 |
(if info1 |
|---|
| 30 |
(push obj2 (rest info1)) |
|---|
| 31 |
(setf (gethash obj1 obj-info) (list 0 obj2)))))) |
|---|
| 32 |
(dolist (obj objects) |
|---|
| 33 |
(let ((info (gethash obj obj-info))) |
|---|
| 34 |
(when (or (not info) (zerop (first info))) |
|---|
| 35 |
(push obj free-objs)))) |
|---|
| 36 |
(loop |
|---|
| 37 |
(flet ((next-result (obj) |
|---|
| 38 |
(push obj result) |
|---|
| 39 |
(dolist (successor (rest (gethash obj obj-info))) |
|---|
| 40 |
(let* ((successor-info (gethash successor obj-info)) |
|---|
| 41 |
(count (1- (first successor-info)))) |
|---|
| 42 |
(setf (first successor-info) count) |
|---|
| 43 |
(when (zerop count) |
|---|
| 44 |
(push successor free-objs)))))) |
|---|
| 45 |
(cond ((endp free-objs) |
|---|
| 46 |
(maphash (lambda (obj info) |
|---|
| 47 |
(unless (zerop (first info)) |
|---|
| 48 |
(error "Topological sort failed due to constraint on ~S." |
|---|
| 49 |
obj))) |
|---|
| 50 |
obj-info) |
|---|
| 51 |
(return (nreverse result))) |
|---|
| 52 |
((endp (rest free-objs)) |
|---|
| 53 |
(next-result (pop free-objs))) |
|---|
| 54 |
(t |
|---|
| 55 |
(let ((obj (funcall tie-breaker free-objs result))) |
|---|
| 56 |
(setf free-objs (remove obj free-objs)) |
|---|
| 57 |
(next-result obj)))))))) |
|---|
| 58 |
|
|---|
| 59 |
;;; simple queue |
|---|
| 60 |
(defun make-queue () |
|---|
| 61 |
(cons nil nil)) |
|---|
| 62 |
|
|---|
| 63 |
(defun queue-empty-p (queue) |
|---|
| 64 |
(null (car queue))) |
|---|
| 65 |
|
|---|
| 66 |
(defun enqueue (x queue) |
|---|
| 67 |
(if (null (car queue)) |
|---|
| 68 |
(setf (cdr queue) (setf (car queue) (list x))) |
|---|
| 69 |
(setf (cdr (cdr queue)) (list x) |
|---|
| 70 |
(cdr queue) (cdr (cdr queue)))) |
|---|
| 71 |
(caar queue)) |
|---|
| 72 |
|
|---|
| 73 |
(defun dequeue (queue) |
|---|
| 74 |
(pop (car queue))) |
|---|
| 75 |
|
|---|
| 76 |
(defun queue-elements (queue) |
|---|
| 77 |
(car queue)) |
|---|
| 78 |
|
|---|
| 79 |
(defun peek-queue (queue) |
|---|
| 80 |
(caar queue)) |
|---|