Lispでリストの中身もすべて反転する関数

このQ&Aのポイント
  • Lispでリストの中身もすべて反転する関数を作成する方法を教えてください。
  • 自作のreverse関数を使用して、リストの中身を反転させる関数を作成したいです。
  • 作りたい関数の動作例として、(make-reverse '(a (b (c d))(e (f g)))) の結果は (((g f) e) ((d c) b) a) です。
回答を見る
  • ベストアンサー

Lispでリストの中身もすべて反転する関数

リストの中身をもすべて反転する関数を作っているのですが、 reverse関数を自分で実装はできたのですが、上記のような使用を持つ関数を作れません。どうぞどのようにしたらよいか教えていただけないでしょうか? ちなみに自分で作ったreverseはこれです。 (defun my-reverse (n) (if (null n) nil (append (my-reverse (cdr n)) (list (car n))))) 作りたい関数では以下のようになります。 (make-reverse '(a (b (c d))(e (f g)))) (((g f) e)((d c) b) a)

質問者が選んだベストアンサー

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

ちょっと答えのぼかし方が良くなかったかも。 > 先頭要素がまたリストだったときの処理として > 再帰的にreverse nをしてみたのですがうまくいきません。 どんな感じのプログラムになったかと、どううまく行かなかったのかを 書いて欲しかったのですが、まあそれはいいでしょう。 > その処理が終わった後にappendにどのように渡すのでしょうか? > appendに渡すときに新たに変数などを使って渡すのかと考えてみましたがうまく実現できません。 変数を使うというのもまあ使えなくはありませんが、Lispらしくはないですね。関数の戻り値をそのまま渡してしまえばいいです。 (car n) が リストだったときに行いたいことは、 (append (my-reverse (cdr n)) ;; cdr部を再帰的に処理した結果 (...) ;; car 部を再帰的に処理した結果 ) ;;これら二つを append する ということなのですがわかりますか? 全体としては (defun my-reverse (n) (if (null n) nil (if (consp (car n)) (append (my-reverse (cdr n)) (xxx (xxxx (xxxx)))) (append (my-reverse (cdr n)) (list (car n)))))) な感じになります。 > まだLisp習いはじめなので質問もおろそかなものですがすいません。 あともうちょい!

sin1224
質問者

お礼

本当にありがとうございます! おかげで何とかできました。Lispというのは初めて扱いましていろいろ わからないこともあったのですが親切丁寧に教えていただいたおかげで 問題がわかりました。 Lispを理解するのにはやはり再帰処理を理解しなくてはいけませんね。 これから勉強するに当たり、今回のような考え方を参考にさせていただきます。 ありがとうございました。

その他の回答 (2)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

>すいませんがもう少しヒントをいただけないでしょうか・・? > 先頭がリストである、という判定にはatomを使えばよいのでしょうか? >その場合そこにおける制御式というのがまだ分かりません・・・ うい。 atomでもできなかないですが、もっと直接的に listp とか conspで良いと思いますよ。 (両者の微妙な違いに注意) 制御式はたとえばCなんかだと if (null(n)) return nil if (listp(n)) .... else append(... のようになるわけですが、あいにくlispにはelseifのようなものはありませんので、 (if (null n) nil (if (consp (car n)) ;;先頭要素がまたリストだったときの処理 (append ... ;;それ以外 のような形になります。 最初のifのelse-partにさらに別のifがくるわけです。

sin1224
質問者

補足

先頭要素がまたリストだったときの処理として 再帰的にreverse nをしてみたのですがうまくいきません。 その処理が終わった後にappendにどのように渡すのでしょうか? appendに渡すときに新たに変数などを使って渡すのかと考えてみましたがうまく実現できません。まだLisp習いはじめなので質問もおろそかなものですがすいません。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

んじゃヒントだけ。 リストの先頭から再帰的に処理していますが、 リストの先頭がリストの場合を考慮しましょう。 つまり、先頭がリストだったらそのリストをreverseしてから append に渡せばいいです。

sin1224
質問者

補足

すいませんがもう少しヒントをいただけないでしょうか・・? 先頭がリストである、という判定にはatomを使えばよいのでしょうか? その場合そこにおける制御式というのがまだ分かりません・・・

関連するQ&A

  • リストを逆順にする関数(LISP)

    「初めての人のためのLISP[増補改訂版]」のP150のリストを逆順に関数がよくわかりません。 以下がその関数です。 (defun nreverse (x) (nrev2 x nil)) (defun nrev2 (x r) (cond ((null x) r) (t (nrev2 (cdr x) x) (rplacd x r) ))) xがnilになるまで再帰を繰り返し、((null x) r) で再帰を戻りますがなぜs (rplacd x r)でリストが逆順になるんでしょうか。例えばxを(a b c)とすると x:(a b c) r:nil ↓ x:(b c) r:(a b c) ↓ x:(c) r:(b c) ↓ x:nil r:(c) ↓ rplacd (c) (b c) ↓ rplacd (b c) (a b c) ↓ rplacd (a b c) nil となるのですが、これじゃあ全然リストは逆順になりませんよね。 誰が教えてください、お願いします。 ちなみにrplacd は第一引数のcdrを第二引数に変換する関数です。

  • LISPでatomの数を数える

    XLISPでlistの中のatomの数を数えたいんです。 下のようにlistの中のatomだけを抜き出してリストにすることはできました。 (DEFUN F1(L) (COND((NULL L) NIL) ((LISTP(CAR L))(F1(CDR L))) (T (CONS (CAR L)(F1(CDR L)))) ) ) このコードを実行すると次のようになります。 (F1 '((A B) C D (E F) G)) (C D G) 後はこれをlengthで数えるだけだと思うのですがそのやり方が分かりません。 それとももしかしてSETQで変数を設定して Tのところで値を1つずつ足していくのでしょうか?

  • 多変数関数の最大値

    7変数の多変数関数をf(a,b,c,d,e,f,g)=19a+18b+17c+16d+15e+13f+11gとする。次の3つ条件をすべて満たす時のfの最大値を求めよ (1)a,b,c,d,e,f,gは0≦a,b,c,d,e,f,g≦98を満たす整数 (2)a+b+c+d+e+f+g=98 (3)3a+4b+5c+7d+8e+10f+12g=544 この問題はどっかの問題集にあったものではなくあるものを求めるために自分で作った問題です。しかしいくらがんばっても自分ではどうすることもできません。この問題はどうすれば解くことができるのでしょうか?この問題を解けるようなフリーソフトを探しましたが見つかりませんでした。もし問題を解けるフリーソフトがあるならそれも教えて欲しいです。

  • LISPの間違いを指摘して欲しいのですが・・・

    (setq a 1) (setq b 2) (setq c 3) (setq d 4) (setq e 5) (setq f 6) (setq g 7) (setq h 8) (setq i 9) (setq j 10) (defun wa(q r s t u v w x y z) (+ q r s t u v w x y z)) (wa a b c d e f g h i j ) 55 1から10までの合計値を求める”LISP”のプログラムを作りたいのですが上記を作ってみましたがうまくいきません。 どこが悪いのでしょうか?

  • LibreOfficeの関数について

    たとえば下記のように、データが入力されているとします。 B5 1月1日 C5 データ1 D5 100 E5 空欄 F5 現金 G5 分類A B6 1月2日 C6 データ2 D6 空欄 E6 200 F6 A銀行 G6 分類B B7 1月3日 C7 データ3 D7 300 E7 空欄 F7 B銀行 G7 分類C B8 1月4日 C8 データ4 D8 空欄 E8 400 F8 C銀行 G8 分類D B9 1月5日 C9 データ5 D9 500 E9 空欄 F9 現金・D銀行 G9 分類E B10 1月6日 C10 データ6 D10 空欄 E10 600 F10 E銀行・現金 G10 分類G このデータを関数を使って、下記のように並べ替えをしたいです。 F列に、現金の文字があるものだけを抽出し、E列の分類が、EもしくはGだったら金額のD部分を入れ替えて表示する。そのほかの分類は、入れ替えをせずにそのまま表示する。 J6 1月1日 K6 データ1 L6 100 M6 空欄 N6 現金 E6 分類A J7 1月5日 K7 データ5 L7 空欄 M7 500 N7 現金・D銀行 E7 分類E J8 1月6日 K8 データ6 L8 600 M8 空欄 N8 E銀行・現金 E8 分類G このようなことを関数で行いたいです。できれば、0やエラー表示は出ないものがいいです。よろしくお願いします。

  • リストのデータを重複なしでランダムに抽出する

    シート1に下記のように14種類の名前リストがあります     A 1   A 2   B 3   C 4   D 5   E 6   F 7   G 8   H 9   I 10  J  11  K 12  L 13  M 14  N 上記の名前を下記のように別シートの数列おきの列(行は同一)に重複なしに行毎にランダムに抽出する事が関数で出来るでしょうか?(エクセルは2010です) ちなみに下記は一列おきのセルに抽出した例です   A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AA 1 D   L   K    I    A   M   N    B   H   J    C    F    E   G 2 K   J   M   H    I   G   F    E   D    A    B   N   C    L 3 E   J   A    L   B   M    K   C   N    G    F   D    H   I どなたか教えていただける方がおりましたらよろしくお願いします。

  • ruby の nil エラー

    rubyで10C0~10C10までの値をすべて合計する 計算をさせようと思って作ったのですが。 定義はうまくできa(10,1)=10と計算できるのですが whileで合計させているところがうまくいきません。 関数的にはあっていると思うのですがnilエラーになってしまい ます。原因はなんなのでしょうか。。。 定義開始 ーーーーーーーーーーーーーーーーーーーーーー def a(g,h) puts a=1 b=1 while a<=g do b = b * a a = a + 1 end c=1 d=1 while c<=h do d = d * c c = c + 1 end e=1 f=1 while e<=g-h do f = f * e e = e + 1 end puts b / ( d * f ) end ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー 定義終了 aa=0 ab=0 while aa <= 10 ab=a(10,aa)+ab aa=aa+1 puts ab end これをすると ab=a(10,aa)+ab ここがNoMethodErrorと表示され 解がでません。 また、ab=a(10,aa)+ab これを ab=a(10,aa) こうすると 解がちゃんとでるのですが。 1 nil 10 nil 45 nil 210 nil . . . となってしまいます。

    • ベストアンサー
    • Ruby
  • エクセル関数

      A  B  C  D  E  F  G 1 10  1  20  1  30  1  8 2 9 2 0 - 0 - - 3 8 3 15 3 23 3 6 4 5 4 19 2 24 2 7 B=Aの順位 、 D=Cの順位 、 E=A+C 、F=Eの順位 、G=Fの得点 の時 G=Fが1の時8、2の時7・・・8の時1、9以下空白 Cが0(ゼロ)の時Dが空白 Eが0(ゼロ)の時Fが空白 上記の場合の関数をどなたか回答よろしくお願いします。 うまく表示できていませんがCとE以外は1桁の数字で、D,F,Gの-は空白です。

  • 関数について。

    実数の定数a,b,c,d,eを係数にもつ2つの関数 f(x)=ax^4+bx^3+cx^2+dx+e g(x)=4ax^2+3bx-2(a-c) を考える。-2≦x≦2を満たす全ての実数xで f(x)≧g(x) であるならば、 max{|a|,|b|,|c|,|d|}≦|e| が成り立つことの証明を教えて下さい。

  • 関数の質問

    エクセル2003を使用しています。 下記のシート1に不規則な空白行があり、それをシート2に空白行を詰めて 表示させたいのですがわかりません。 関数でよろしくおねがいいいたします。 シート1 A B C D E F G 1 1 1 1 1 1 1 1 2 3 2 2 2 2 2 2 2 4 3 3 3 3 3 3 3 5 6 7 4 4 4 4 4 4 4 8 9 5 5 5 5 5 5 5 10 11 12 13 6 6 6 6 6 6 6 14 7 7 7 7 7 7 7 15 8 8 8 8 8 8 8 16 9 9 9 9 9 9 9 17 18 シート2 A B C D E F G 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 8 8 8 8 8 8 8 8 9 9 9 9 9 9 9 9 10 11 12 13 14 15 16 17 18 ・ ・ ・ ・

専門家に質問してみよう