2

単純な (1 次元の) リストの要素を逆にする必要があります。組み込みのリバース機能があることは知っていますが、これには使用できません。

これが私の試みです:

(defun LISTREVERSE (LISTR)
    (cond
        ((< (length LISTR) 2) LISTR) ; listr is 1 atom or smaller
        (t (cons (LISTREVERSE (cdr LISTR)) (car LISTR))) ; move first to the end
    )
)

出力はかなり近いですが、間違っています。

[88]> (LISTREVERSE '(0 1 2 3)) 
((((3) . 2) . 1) . 0)

だから私はappend代わりに使用しようとしましたcons

(t (append (LISTREVERSE (cdr LISTR)) (car LISTR)))

しかし、このエラーが発生しました:

*** - APPEND: A proper list must not end with 2

何か助けはありますか?

4

4 に答える 4

6

これは宿題のように見えるので、私はあなたにいくつかの指針を与えることができます:

  • 再帰の基本的なケースは、リストが空(null)の場合であり、リストに含まれる要素が2つ未満の場合ではありません。
  • 空のリストで初期化された「アキュムレータ」という追加のパラメータを使用してヘルパー関数を定義することを検討してください。元のリストの各要素について、consそれはアキュムレータの先頭にあります。入力リストが空の場合、アキュムレータを返します

余談ですが、上記のソリューションは末尾再帰です。

于 2012-04-19T03:09:15.280 に答える
3

Óscar López のフォローアップとして (そして、別の解決策を書き留めたいという誘惑と戦ってください):

  • 両方appendを使用lengthすると、投稿されたソリューションは、リストを逆にする最も効率の悪い方法になります。これを実装する方法に関するいくつかのより良いアイデアについては、ドキュメントを参照してくださいconsnull
  • ちゃんと インデントしてください。
  • この場合、末尾再帰は実際にはより効率的であり、かなり単純です。まだ試していない場合は試してみてください。labelsローカル再帰関数を定義するために使用する形式です。
  • The Little Schemerをめくってみる価値はあるかもしれません。一般的に、再帰の感覚が良くなります。
于 2012-04-19T14:05:31.490 に答える
0
(defun listreverse (list)
  (let (result)
    (dolist (item list result)
      (push item result))))
  • 同じ目標に到達する単純な反復方法がある場合、Common Lisp で再帰を使用しないでください。Common Lisp は末尾再帰について何の保証もせず、末尾再帰関数の呼び出しは、コンパイラの裁量でジャンプに最適化されない場合があります。
  • push項目を結果の先頭に追加します
  • dolist返される値であるオプションの 3 番目の引数があります。ループを抜けるときに評価されます。
于 2013-03-17T19:33:05.580 に答える
0

あなたがしたことは大丈夫です。結果リストの構成を見逃しただけです。

考えてみてください: 逆の CDR のリストの最後に、CAR の 1 要素リストを追加する必要があります。

(defun LISTREVERSE (LISTR)
    (cons
        ((< (length LISTR) 2) LISTR) ; listr is 1 atom or smaller
        (t (append (LISTREVERSE (cdr LISTR)) (list (car  LISTR))))))
于 2012-04-20T20:11:42.417 に答える