2017-09-25 8 views
0

from_to/3を実装するように練習していましたが、ここでは最初の2つの引数として2つの数値を指定し、結果としてそれらの間のすべてのリストを提供します。たとえば、​​はR=[1,2,3,4,5]となります。それは5 3のリストを返すクエリfromto(3,8,R)なぜこれらの同様のプログラムは異なる成果をもたらしますか?

fromto(N, O, []):- 
    N >= O. 
fromto(N, O, [N|TailResult]):- 
    O > N, 
    O1 is O-1, 
    fromto(N, O1, TailResult). 

は、私は次のプログラムを書きました。良くない。それを処理するための 正しい方法は次のようになります。

from_to(N, O, []) :- 
    N > O. 
from_to(N, O, [N|TailResult]) :- 
    N =< O, 
    N1 is N + 1, 
    from_to(N1, O, TailResult). 

意図したとおりこれはlist 3,4,5,6,7,8を与えます。

私の質問はこれがどのように機能するかです。プログラムは、私がOを使って上から下に作業し、正しいものがNに追加することによって上向きに働くという点だけが異なります。しかし、結果は全く異なります。 これを引き起こす原因を知っている人はいますか?

答えて

2

問題は、最初の引数-NはOの変更だけを変更するのではなく、Nをリストに再帰的に配置することで、Nのリストが表示されることになります。

あなたがこのアプローチを維持したい場合は、リスト内の各時間Oを配置する必要があります。

fromto(N, O, []):- 
    N > O. 
fromto(N, O, L):- 
    O >= N, 
    O1 is O-1, 
    fromto(N, O1, L2), 
    append(L2,[O],L). 

この実装での問題は、あなたが他のあなたの右の順に配置するためにappend/3を使用する必要があるということです逆のリストを取得します。リスト内の要素を追加する必要があるたびに、すべてのリストをトラバースして追加のオーバーヘッドを与えるendeに配置する必要があるため、効率的ではありません。

例:@Falseにより示唆されるように

?- fromto(3,8,L). 
L = [3, 4, 5, 6, 7, 8] ; 
false. 

また、あなたはDCGを使用することができます。

from_to(N,N) -->[N]. 
from_to(N,O) --> [N],{N<O, N1 is N+1},from_to(N1,O). 

final_solution(N,O,L):- phrase(from_to(N,O),L). 

そして、他の方法(Nの代わりにOを減らす):

from_to(N,N) -->[N]. 
from_to(N,O) --> {N<O, O1 is O-1},from_to(N,O1),[O]. 

final_solution(N,O,L):- phrase(from_to(N,O),L). 

を今、2つの解決方法は、2番目の節の順序を変更するだけで非常に似ています。

+1

'append/3'を使用する代わりに、[tag:dcg] -notationを使用して2つのアプローチを定式化することがより洞察になります。 – false

+0

@falseあなたは右にdcgソリューションが追加されています。 – coder

関連する問題