3

私は LISP でこの宿題を持っています。ここでは、リストからアトムとサブリストを整理する必要があります。これは簡単な作業だと思いますが、私はあまりプログラマーではないので、理解するのにかなり時間がかかります。

私はこの番号のリストを持っています:

(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6)

そして、自分のタスクを正しく理解していれば、次のようなものが得られるはずです:

(5 -1 -6 (2 6 1) (8 7 -3) (0 (9 4)))

これまでのところ、アトムやサブリストを数える方法しかわかっていませんが、それは必要ありません。

(DEFUN ATOMNUMBER (L) (COND ((NULL L) 0)
  ((ATOM (CAR L)) (+ 1 (ATOMNUMBER (CDR L))))
  (T (ATOMNUMBER (CDR L))) ))

また、サブリストのみ、アトムのみ、または空のリストのみがある場合でも、その関数は正しく機能するはずです。

誰かが私に例を挙げてくれるでしょうか?

前もって感謝します!

4

5 に答える 5

7

Common Lisp にはいくつかの可能なアプローチがあります:

  • REMOVE-IF を使用して不要なアイテムを削除します。(代わりに REMOVE-IF-NOT を使用して、必要な項目を保持します。) 2 つのリストが必要になります。それらを追加します。

  • DOLIST を使用してリストを反復処理し、項目を 2 つのリストに収集して追加します

  • 2 つの結果リストを保持する必要がある再帰プロシージャを記述します。

  • 特別なソート述語で SORT を使用することも可能です。

例:

> (sort '(1 (2 6 1) 4 (8 7 -3) 4 1 (0 (9 4)) -6 10 1)
        (lambda (a b)
           (atom a)))

(1 10 -6 1 4 4 1 (2 6 1) (8 7 -3) (0 (9 4)))

安定版として:

(stable-sort '(1 (2 6 1) 4 (8 7 -3) 4 1 (0 (9 4)) -6 10 1)
             (lambda (a b)
               (and (atom a)
                    (not (atom b)))))

(1 4 4 1 -6 10 1 (2 6 1) (8 7 -3) (0 (9 4)))
于 2012-05-13T17:24:39.110 に答える
2

私はSchemeに慣れていますが、Lispで機能するソリューションは次のとおりです。

(defun f (lst)
  (labels 
      ((loop (lst atoms lists)
         (cond
          ((null lst) 
           (append (reverse atoms) (reverse lists)))
          ((atom (car lst))
           (loop (cdr lst) (cons (car lst) atoms) lists))
          (T
           (loop (cdr lst) atoms (cons (car lst) lists))))))
    (loop lst '() '())))

(f '(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6))

基本的に、リストを反復処理し、各要素がアトムリストまたはリストリストに追加されます。最終的には、両方に参加して結果を取得します。

編集

もちろん、remove-ifバージョンははるかに短いです。

(let ((l '(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6)))
   (append
    (remove-if-not #'atom l)
    (remove-if     #'atom l)))
于 2012-05-13T21:01:12.957 に答える
0

もっと運動したい場合に備えて、ここで提供されている例では不十分であることがわかります:P

(defun sort-atoms-first-recursive (x &optional y)
  (cond
    ((null x) y)
    ((consp (car x))
     (sort-atoms-first-recursive (cdr x) (cons (car x) y)))
    (t (cons (car x) (sort-atoms-first-recursive (cdr x) y)))))

(defun sort-atoms-first-loop (x)
  (do ((a x (cdr a))
       (b) (c) (d) (e))
      (nil)
    (if (consp (car a))
      (if b (setf (cdr b) a b (cdr b)) (setf b a d a))
      (if c (setf (cdr c) a c (cdr c)) (setf c a e a)))
    (when (null (cdr a))
      (cond
        ((null d) (return e))
        ((null c) (return d))
        (t (setf (cdr b) nil (cdr c) d) (return e))))))


(sort-atoms-first-recursive '(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6))

(sort-atoms-first-loop '(5 -1 (2 6 1) (8 7 -3) (0 (9 4)) -6))

2つ目は破壊的です(ただし、新しい結果は作成されません)。

于 2012-05-14T23:54:41.313 に答える
0

以下は、トップダウン方式で出力を構築する反復コードです (コメントは Haskell 構文です)。

;atomsFirst xs = separate xs id id where
;  separate [] f g  = f (g [])
;  separate (x:xs) f g
;      | atom x = separate xs (f.(x:)) g
;      | True   = separate xs f (g.(x:))

(defmacro app (l v)
   `(progn (rplacd ,l (list ,v)) (setq ,l (cdr ,l))))

(defun atoms-first (xs)
  (let* ((f (list nil)) (g (list nil)) (p f) (q g))
    (dolist (x xs)
      (if (atom x) (app p x) (app q x)))
    (rplacd p (cdr g))
    (cdr f)))

トップダウン方式で構築されている 2 つの中間リストは、基本的に差分リスト パラダイムに従って、制限のないリスト (つまり、明示的な終了ポインターを使用) として維持されます。

于 2012-05-14T13:27:15.230 に答える