2012-04-16 10 views
1

私はPrologを完全に使いこなしており、宿題に取り組んでいます。私のプログラムは、等しい長さの2つのリストを取って、D = sqrt((X1-Y1)^ 2 +(X2-Y2)^ 2 + ... +(XN-YN)^ 2)私は正しい答えを得るためのコードを書いたが、正しく提示していない。私はそれが無限ループで終わっているように思えるので、ロジックの流れに問題があると思います。ように見えることになっています:プロローグのロジックフロー

?- distance([1,2,3], [2,3,4], D). 
D = 1.732051. 

私のコードは私に正しい結果を与えているが、それはそれが好きで出力します。

?- distance([1,2,3],[2,3,4],D). 
1.732051 
true 

をそして、私はそこにラインを持っているという理由だけで結果を印刷します。それはまた私がenterを押すまで終わらない(期間なし)ので、私はループがあるのを恐れている。それを正常に印刷するには、コードを書き換えたり、ロジックをリダイレクトしたりするにはどうすればよいですか?あなたのプログラムが無限ループに入らない

distance([],[],D) :- 
    F is sqrt(D), 
    format("~f~n", [F]). 

distance([A|T1], [B|T2], D) :- 
    var(D), 
    S is (A-B)*(A-B), 
    distance(T1, T2, S); 
    C is A-B, 
    E is C*C, 
    F is D+E, 
    distance(T1, T2, F). 
+0

は 'F'はない' D + E'、 'D-E'に評価されていないでしょうか?再帰的な距離は、全体の距離から毎回最初の語句までの距離を引いた値にする必要があります。私はまた、 'distance(T1、T2、S);という行で混乱しています;それについてあなたはおそらくコメントできますか? – ely

+0

N/M、私はあなたが今何をしているのかを見ています。最後の議論での距離の合計を累計しています。私は少し難解だと思うが、正しい。唯一の問題は奇妙な印刷です私はこれがあなたの本当の根拠の欠如に関連していると思う。あなたの方法では、距離([]、[]、0)は真ではありません。また、実行時にコードがハングアップし、余分な 'を待っていることに注意してください。真を返した後 – ely

答えて

2

は、そうでなければ、最も可能性の高いいくつかの時点でスタックオーバーフローエラーになるだろう。 何が起こっているのか、あなたのコードはオープンな選択肢を残すため、最終的にインタプリタはやり直しを試みます(失敗すると)。 呼び出し元のプロシージャで使用された変数Dが決してバインドされないため、結果が期待どおりに取得されません。

再帰的にモデル化する方法を考えて、この問題を解決するほうがよいでしょう。この場合、たとえば入力リストが空のときとそうでないときに問題を分割することができます(空のリストを使ってプロシージャを呼び出すと結果として0が返されます)。

したがって、このシナリオでは、基本ケース(空リスト)と再帰ステップの2つの節を作成します。また、アキュムレータを使用するプロローグで使用される共通のアプローチを使用します。

だから我々はちょうどこのアキュムレータを使用する別のプロシージャを呼び出します距離/ 3のための実際の作成:

distance(L1,L2,F) :- 
    distance(L1, L2, 0, F). 

我々は平方アイテム差(AB)の和の部分的な結果を保持するために、アキュムレータを使用しますあなたのコード内で*(AB):

今、我々はベースケース(空のリスト)を開始します。

distance([],[],S,F) :- 
    F is sqrt(S). 

ここでは述べるもう項目が残っていない結果そのI sはアキュムレータの平方根です。

次に、各リストの最初の項目の二乗された項目の差異を計算し再帰を実行する再帰的な手順を実行します。今、私たちが行っている

distance([A|T1], [B|T2], D, SQRT) :- 
    S is D+(A-B)*(A-B), 
    distance(T1, T2, S, SQRT). 

?- distance([1,2,3],[2,3,4],D). 
D = 1.7320508075688772. 
+0

もちろん!すべてを非常にはっきりと簡潔に説明してくれてありがとう。私はあなたが私に与えた変更を使用し、今それは動作します。ありがとう! – AmberWolfe

0

を私はそう私にできることすべては、この時の私自身の試みを提供され、format機能の使用を理解していません。あなたの試みには、再帰の基底ケースの観点からは明確に述べられていないという欠点があると思います。私はあなたがアキュムレータを使うべきだと思う

distance([],[],0). 
distance([A],[A],0). 
distance([A|T1],[B|T2],D) :- 
    distance(T1,T2,F), 
    D is sqrt((A-B)*(A-B) + F*F). 
+0

別の関数を計算していることに注意してください。たとえば、(A1-B1)^ 2 + sqrt((A2-B2)^ 2 + sqrt((A3-B3)^ 2)^ 2)^ 2'という3つの項目のリストを使用します。また、2番目のベースケースは必要ありません。 – gusbro

+0

2つめのベースケースを使用しない方が速くなるでしょうか?おそらく数値的に頑強であるかもしれません(通常これはPrologでは問題ではありません)。 – ely

+0

問題はあまり明確ではないということです。より速く、より堅牢にしたい場合は、尾部の再帰を可能にするためにアキュムレータを使用する必要があります(それ以外の場合は、スタックの問題があるかもしれません) – gusbro

0

は、以下の私のアプローチを考えてみましょう

distance(L1, L2, D) :- 
    distance(L1, L2, 0, D). 

distance([], [], TT, D) :- 
    D is sqrt(D). 

distance([X1 | Y1], [X2 | Y2], TT, D) :- 
    TT1 is TT + (X1 - X2) * X1 - X2), 
    distance(Y1, Y2, TT1, D).