2015-11-28 45 views
1

我想從數在各個層面(表面的層次)LISP

Ex: (1 2 5 (4 2 7 (4 6) 9) 7 8) => (8 9 6) 

的名單我現在有什麼計算最大每一子表/平/膚淺的層面的最大數量爲:

maximum (l) ;;function to compute the maximum number for a simple list, it works 

(defun max-superficial (lista acc acc2) ;;main function: lista - my list, acc - my final list 
             ;;of results, acc2 - accumulation list for a sublist 
    (typecase lista 
     (null 
      (typecase acc2 

;; if my list is empty and I have nothing accumulated, just return the final list 
       (null acc) 

;;if my list is empty but I have something in my accumulation list, just add the maximum 
;;of acc2 to my final list 
       (t (nconc acc (list (maximum acc2)))))) 

     (cons (destructuring-bind (head . tail) lista 
      (typecase head 
       (list 

;;if my list isn't empty and the head of the list is a list itself, call 
;;the function again for the head with an empty accumulation list and then call it again 
;;for the tail 
          (nconc acc 
           (list (max-superficial head acc nil)) 
           (max-superficial tail acc acc2))) 

;; otherwise just accumulate the head and call the function for the tail 
---problem here    (t (nconc acc2 (list head)) 
          (print '(wtf)) 
          (print acc) 
          (print acc2) 
          (print head) 
          (max-superficial tail acc acc2))))))) 

問題是我只寫這個程序,我想測試它,並在列表「---問題在這裏」它不會把我的頭添加到累積列表。

For: (max-superficial '(1 2) nil nil) --result should be ==> wtf nil (1) 1 wtf nil (1 2) 2 2 
                My result: wtf nil nil 1 wtf nil nil 2 nil 

我單獨檢查和(nconc some-list (list 3))不正是它應該...添加3號到一些名單的後面。我不知道爲什麼nconc acc2 (list head)不工作

試圖用append替換nconc,它也不工作。顯然,您不能使用append/nconc將元素添加到空列表中。那怎麼樣?

+0

我在此刻移動,不能詳細閱讀所有的代碼,但請注意,nconc具有破壞性:它修改了除最後一個參數外的最後一個cdr。你也在使用一些引用列表。這可能會導致一些意想不到的結果。 –

+0

請參閱http://stackoverflow.com/questions/18790192/unexpected-persistence-of-data –

+0

確實用'append'替換'nconc'解決您的問題? – sds

回答

1

更簡單的實現:

(defun max-superficial/sublists (list) 
    (loop for num in list 
     if (listp num) append (max-superficial/sublists num) into sublists 
     else if (numberp num) maximize num into max 
     else do (error "Not a number or list: ~a" num) 
     finally (return (cons max sublists)))) 

;; If you want the max of each "level" or depth in a tree, 
;; then you need to be able to operate on levels. Here are some 
;; functions that are analogous to FIRST, REST, and POP: 

(defun top-level (tree) 
    (remove-if-not #'numberp tree)) 

(defun rest-levels (tree) 
    (apply #'append (remove-if-not #'listp tree))) 

(defmacro pop-level (tree) 
    `(let ((top (top-level ,tree))) 
    (setf ,tree (rest-levels ,tree)) 
    top)) 

(defun max-superficial (tree &key use-sublists) 
    "It wasn't clear if you wanted the max in each sublist or the max 
at each depth, so both are implemented. Use the :use-sublists key 
to get the max in each sublist, otherwise the max at each depth 
will be computed." 
    (if use-sublists 
     (max-superficial/sublists tree) 
     (loop for top-level = (pop-level tree) 
     collect (if top-level (reduce #'max top-level)) into result 
     unless tree do (return result)))) 
+0

這是否應該爲''(1(2(3)))和''(1(2)(3))'返回'(1 2 3) ? (這從OP不太清楚......) – gsg

+0

他提到了「子列表」和「關卡」。我更新了代碼以根據'&key'參數在層次或子列表上進行操作。 –

+0

看起來不錯,但我應該只使用lisp的基本操作,以免與樹木一起工作。 @gsg(1 2 3)是正確答案。我在那裏舉了一個例子,你可以清楚地看到我的意思。 – Mocktheduck

0

這裏有一個(不是特別有效)解決方案:

(defun max-avoiding-nil (a b) 
    (cond ((null a) b) 
    ((null b) a) 
    (t (max a b)))) 

(defun depth-maximum (a b) 
    (cond ((null a) b) 
    ((null b) a) 
    (t 
    (cons (max-avoiding-nil (car a) (car b)) 
      (depth-maximum (cdr a) (cdr b)))))) 

(defun tree-max-list (list depth) 
    (reduce #'depth-maximum tree 
      :key (lambda (elt) (tree-max elt depth)) 
      :initial-value '())) 

(defun tree-max (tree depth) 
    (if (listp tree) 
     (tree-max-list tree (1+ depth)) 
    (append (make-list depth 'nil) (list tree)))) 

(defun tree-maximums (tree) 
    (tree-max-list tree 0)) 

(tree-maximums '(1 2 5 (4 2 7 (4 6) 9) 7 8)) => (8 9 6) 
(tree-maximums '()) => nil 
(tree-maximums '(1)) => (1) 
(tree-maximums '((2))) => (nil 2) 
(tree-maximums '((2) (3))) => (nil 3) 
+0

我不應該使用像reduce或#,:,lambda這樣的函數。我是初學者,我想解決這個問題,我只能使用列表的最基本的方式 – Mocktheduck