(defun idea (tbl &optional (enough 2)) (with-slots (rows left right break c east west) tbl (when (>= (length rows) enough) (let* (all half above below (any (anyv rows)) ; 1) pick anything (west1 (furthest tbl any rows))) ; 2) find furthest from (1) (multiple-value-bind (east1 c1) (furthest tbl west1 rows) ; 3) find furthest from (2) (setf c c1 ; 4) update tbl with results from 1,2,3 west west1 east east1) ; 5) sort the rows along a line running west to east (setf all (rows-sorted-west-to-east tbl rows west east c)) ; 6) split the rows (setf half (floor (/ (length all) 2)) below (sub-table tbl (vector! (subseq all 0 half))) above (sub-table tbl (vector! (subseq all half)))) ; 7) fund the break (setf break (location-of-break tbl below west east c)) ; 8) update the pointers in the tree (setf left below right above (table-up left) tbl (table-up right) tbl) ; 9) recurse (idea left enough) (idea right enough))))) tbl) (defun sub-table (tbl new-rows) (let ((out (copy-table tbl))) (with-slots (color gray? left right up break c east west rows) out (setf left nil right nil up nil color nil gray? nil break nil c nil east nil west nil) (setf rows new-rows)) out)) (defun location-of-break (tbl below west east c) (let ((last-row-below (svref (table-rows below) (1- (length (table-rows below)))))) (x (dist tbl last-row-below west) (dist tbl last-row-below east) c))) (defun rows-sorted-west-to-east (tbl rows west east c &aux all) (dov (one rows) (let ((place (x (dist tbl one west) (dist tbl one east) c))) (push (cons place one) all))) (mapcar #'cdr (sort all #'< :key #'car))) (defun x (a b c) "Find x of (x,y) that is distance 'a' from (0,0) and 'b' fron (c,0)" (cond ((zerop c) 0) ((>= b c) 0) ; not really true, but we only need to divide, so fair enough ((>= a c) c) ; ditto (t (/ (+ (* a a) (* c c) (* -1 b b)) (* 2 c))))) (defun y (a x) "Find x of (x,y) that is distance 'a' from (0,0) and 'b' fron (c,0)" (sqrt (+ (* a a) (* -1 x x)))) (let (n) (defun printt (tbl &key (depth 0) (pre "") (str t) (pad "| ") (max-depth 50)) (when tbl (with-slots (rows gray? left right color c west east break) tbl (let* ((m (length rows)) (dist-display (if (= 1 m) 0 (round (* 100 c)))) (break-display (if (<= m 3) "" (format nil "/ ~a" (round (* 100 break))))) (color-display (if color (format nil "[~(~a~)]" color) ""))) (if (zerop depth) (setf n 0)) (format str "~5a~a " (incf n) (if gray? "?" "!")) (dotimes (i depth) (format str "~a" pad)) (format str "~a~a at ~a ~a looks ~(~a~) ~a~%" pre m dist-display break-display (zeror tbl) color-display) (when (< depth max-depth) (printt left :depth (1+ depth) :pre "< " :str str :pad pad ) (printt right :depth (1+ depth) :pre "> " :str str :pad pad )))))) ) ;;;;;;;;;;;;;;;;;; (defmethod print-object ((tbl table) str) (format str "#T(:c ~a :break ~a :rows ~a)" (table-c tbl) (table-break tbl) (length (table-rows tbl)))) (defun data2tree (f &optional (enough 30)) (idea (data (string-downcase (format nil "data/~a.lisp" f))) enough)) (deftest !idea0 (&optional (f 'labor) (enough 2)) (let (out) (time (setf out (data2tree f enough))) out)) (deftest !idea1 () (dolist (what '( 2 4 8 16 20 32 64 81 128)) (!idea1-prim "data/autos32.lisp" what))) (defun !idea1-prim (f &optional (enough 30)) (let ((tbl (data f)) time) (print 1) (setf time (time-it 1 (idea (data f) enough))) (print `(,enough ,time))))