LISPによる横型探索プログラムの経路出力方法

このQ&Aのポイント
  • LISPのSchemeを使用して横型探索で探索した経路を出力するプログラムを作成する方法を教えてください。
  • 現在のプログラムは探索が終わると終了するため、経路の出力ができません。
  • 経路の出力機能を追加するには、展開済みリストCLOSEDに探索した経路を追加する必要があります。
回答を見る
  • ベストアンサー

LISPによる横型探索

LISPのSchemeをつかって横型探索で探索した経路を出力するプログラムをつくっているのですが、 今は探索が終わると終了するとCLOSEDの中を表示するプログラムしかできていません もしこれに探索した経路の出力をする機能を加える場合どうすればいいですか? OPEN→待ちリスト CLOSED→展開済みリスト GOAL→目標地点 OP→オペレータの集まり nとopから展開の結果をだす (define (tenkai n op) (tenkai2 n op '())) (define (tenkai2 n op kekka) (if (null? op) kekka (if (= n (car (car op))) (tenkai2 n (cdr op) (cons (car (cdr (car op))) kekka)) (tenkai2 n (cdr op) kekka)))) (define (yokogata open goal op closed) (if (null? open) 'sippai (if (= (car open) goal) (display closed) (yokogata (append (cdr open) (tenkai (car open) op)) goal op (append closed (list (car open)))))))

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

  • ベストアンサー
回答No.1

う~~ん……。 こう言うのって検索対象の「データ構造」が分かんないと何とも言えないですよね。 結局二分木探索でしょ?その二分木探索対象のリストが「どう言う構造なのか?」で全然違うんですよ。表現方法が色々ある。だから特定出来ませんね。 また、opと言われても「一体何をさせたいのか?」不明です。演算子の集合、っつってもどう言う集合なんだか皆目不明ですし。 一般的な幅優先探索の簡単なコードは、ポール・グレアムの「ANSI Common Lisp」によれば次のような感じです。Scheme用に書き換えてあります。 (define (shortest-path start end net)  (breadth-first-search end (list (list start)) net)) (define (breadth-first-search end queue net)  (or (null? queue)     (let ((path (car queue)))      (let ((node (car path)))       (if (eqv? node end)         (reverse path)         (breadth-first-search end                    (append (cdr queue)                        (new-paths path node net))                    net)))))) (define (new-paths path node net)  (map   (lambda (n)    (cons n path))   (cdr (assoc node net)))) netに探索したい二分木リスト、startに探索始点、endに探索終点を与えると経路のリストを返します。 例えば、家系図リスト、familyを次のように設定します。 (define family '((Harry Jane Bill) (Jane Joe Diane) (Joe '() '()) (Dian '() ())          (Bill Julia Mike) (Julia Frank Susan) (Frank Anne '()) (Susan '() '())          (Mike '() '()))) このリストの各要素は(ノード 子供左 子供右)となっていて、左の枝から順に整列しています。 この二分木リストをnetに与え、例えばBillからFrankへの系図を辿るには、 > (shortest-path 'Bill 'Frank family) (Bill Julia Frank) となりますね。つまり、Billの子供の一人がJuliaで、Juliaの子供がFrankです。つまり、FrankはBillの孫ですよね。 こう言う感じで経路を記録していくんですが、参考になったでしょうか?

tutunana
質問者

お礼

お礼が大変遅くなってすいません。 かなり参考になり、無事完成しました。 本当にありがとうございます

関連するQ&A

  • Lispにおける最大値関数

    Lispで括弧の入れ子の中身も含めた最大値を求める関数を自分なりに作ったのですが、条件によってはうまくいきません。 なぜだか教えていただけないでしょうか? (defun max1 (n) (cond ((atom n) n) (t (if (null (cdr n)) (max1 (car n)) (progn (let ((local_max (max1 (cdr n)))) (if (> (car n) local_max) (car n) local_max))))))) > (max1 '(1 2 6 (3 4))) 6 > (max1 '(1 2 (6) ((3 4)))) >: (6) is not a REAL

  • 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)

  • Lispについてわからないことが(Scheme)

    あるLispの勉強ソフトで、 「関数lを『引数としてxを受け取ると、xの要素の数を返す関数』として定義しなさい。」 という問題があるのですが、私は以下のようにしました。 (define l (lambda (x) (if (= x null?) 0 (+ 1 (l (cdr x)))))) しかしこれだとオーバーフローと表示されて強制終了されてしまいました。 そこで答えをネットで検索したところ以下のものが見つかりました。 (define l (lambda (x) (cond ((null? x) 0) (else (+ 1 (l (cdr x))))))) これが正解なようですが、この2つのリストの違いがわかりません。 初歩的なことですがifの使い方を間違っているんでしょうか?

  • Schemeの質問

    最近Schemeを習い始めたのですがlambdaの概念がよく分かりません。 適当に見つけた例題やらを見ながら、末尾再帰法でリストの中から一番小さい数を表示する関数を書きました。リストが空なら'()を返します。 (define (small List) if (null? List a) '() (small2 List 0))) (define small2 (lambda (list a) (cond ((null? List) a) (or (= head 0) (> head (car List))) (small2 (cdr List) (car List))) (else (small2 (cdr List) a))))) 一応ちゃんと動くのですが、無駄にいっぱい書いている気がします。lambdaを使わない方が短くできるんでしょうか?lambdaを使うべきなのか使わないべきなのかの判断がうまくできません。

  • common lispのコード

    リスト中の要素aの数をカウントするプログラムを反復で書いたのですが、実行しようとすると停止してしまいます。何が悪いのでしょうか?教えてもらえませんか? (defun dot (lst) (let ((c 0)) (do ((ls lst (cdr lst)) ((null ls) c) (if (eq 'a (car ls)) (+ c 1) (+ c 0)))))

  • scheme

    リストに含まれる記号の数を求める手続きを作りたいのですが。 (0 -1 -2 -3) この場合は0を返す (pooh piglet 2001)  この場合は2を返す (1192 538 (owl rabbit))  この場合は2を返す 再帰を使うのですがうまくいきません。 1つめと2つめの例はできるのですが、3つめは中にリストがあって そのリストの中も数えるところがよくわかりません。 (define (count x) (if (null? x) 0 (if (number? (car x)) (count (cdr x)) (+ (count (cdr x) 1))))) これだとうまくいきませんでした。 おねがいします。

  • 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つずつ足していくのでしょうか?

  • 落ちてしまいます

    無限ストリームなのですが、 (define (stream-car stream) (car stream)) (define (stream-cdr stream) (force (cdr stream))) (define (cons-stream a b) (cons a (delay b))) (define (integers-starting-from n) (cons-stream n (integers-starting-from (+ n 1)))) (define integers (integers-starting-from 1))      (define (stream-ref s n) (if (= n 0) (stream-car s) (stream-ref (stream-cdr s) (- n 1)))) (define (divisible? x y) (= (remainder x y) 0)) (define (sieve stream) (cons-stream (stream-car stream) (sieve (stream-filter (lambda (x) (not (divisible? x (stream-car stream)))) (stream-cdr stream))))) (define primes (sieve (integers-starting-from 2))) (stream-ref primes 10) integersを定義する段階で落ちてしまうようです。どうも遅延評価がうまくいってないようです。どうしたらよいでしょうか?どなたか助けてください。

  • schemeでリストの中にリストができてしまう。

    (define (find i . elements) (if (eq? i (car elements)) 'Matched! (find2 i (cdr elements)))) (define (find2 i elements) (if (eq? i (car elements)) 'Matched! (find2 i (cdr elements)))) 上記を一つのfunctionにまとめることはできないでしょうか? 現在二つに分けている理由は(eq? i (car elements))が偽だったときに実行される(cdr elements)がリスト(例 '(a b c))なので、そのままfindを呼んでしまうとfindは(i . elements)を取るため、elementsが'((a b c))となってしまうからです。find2を使い、そのような「リストの中のリスト」を作らないようにしています。 find2を使わず一つにまとめられる方法はないでしょうか?お願いします。

  • Shemeで

    Shemeで 関数map1を引数を1つとる関数と リストの2つの引数をとる、簡易版のmapとして定義しなさいという問題で 以下のように考えたのですがうまくいきません。 (define map1(lambda (f l) (if (null? l) (quote()) cons(f (car l) (map1 f (cdr l)))))) ご教授お願いします。

専門家に質問してみよう