2016-09-24 4 views
0

問題があります。私はreplace(E1、L1、E2、L2)述部を実装したいと思います。 これは、L1とL2が同じリストである場合を除いて、L1がE1、L2にE2を持つ1つの場所を除きます。さらに、1つのオカレンスだけが置換され、どのモードでも動作する必要があります。例えばエラー:グローバルスタックにappend/3があります。

replace(2,[1,2,3,4],5,X)が唯一の解決策X = [1,5,3,4]を持つ必要があります。

replace(2,[1,2,3,2,1],5,X)は、ソリューションX = [1,5,3,2,1]X = [1,2,3,5,1]をバックトラックする必要があります。

replace(2,X,5,[1,5,3,5,1])は、ソリューションX = [1,2,3,5,1]X = [1,5,3,2,1]をバックトラックする必要があります。

replace(X,[a,b,c,d],Y,[a,e,c,d])には、解決策X = b, Y = eが必要です。

replace(X,[1,2,3,2,1],Y,[1,5,3,5,1])には解決策がありません( は失敗するはずです)。

私の実装:

replace(E1, L1, E2, L2) :- 
    append(X, [E1|L_Tail], L1), 
    append(X, [E2|L_Tail], L2). 

このコードは結構です。ただし、replace(2,X,5,[1,5,3,5,1])の場合は、X = [1,2,3,5,1]X = [1,5,3,2,1]falseが返されます。最初の2つの結果しか返さず、falseが出てこなかった。プログラムはERROR: Out of global stackになります。

答えて

2

This questionの2つの回答:one you usedbetter oneがあります。しかし、私は "このソリューションはなぜ機能しないのか、それを修正する方法は?"という質問に答えます。

append/3への3番目の引数が変数またはリストの一部である、それは無限に多くのソリューションを提供します:最初のリストL1がリストの一部であるときに

?- append(X, Y, [a|Z]). 
X = [], 
Y = [a|Z] ; 
X = [a], 
Y = Z ; 
X = [a, _1860], 
Z = [_1860|Y] ; 
X = [a, _1860, _1872], 
Z = [_1860, _1872|Y] ; 
X = [a, _1860, _1872, _1884], 
Z = [_1860, _1872, _1884|Y] . % and so on 

を、append(X, [E1|Y], L1)の呼び出しは、「続けます幻覚的な "長いリストと長いリスト。 append/3への2回目の呼び出しは毎回失敗し、Prologはバックトラックし、さらに最初のappend/3でさらに長いリストを作成します。このため、無限ループに巻き込まれ、最終的にはメモリ不足になります(リストが長すぎる場合)。

これを避けるための安価な方法は、両方のリストが同じ長さの適切なリストであることを確認してから、2つのappendにそれらを与えることです。たとえば、次のように

same_length([], []). 
same_length([_|A], [_|B]) :- same_length(A, B). 

あなたがmaplistとyallラムダでこれを行うことができSWI-Prologのを使用している場合:

maplist([_,_]>>true, L1, L2) 

クエリの例:それが動作

?- L2 = [1,5,3,5,1], 
    maplist([_,_]>>true, L1, L2), 
    append(X, [2|Y], L1), 
    append(X, [5|Y], L2). 
L2 = [1, 5, 3, 5, 1], 
L1 = [1, 2, 3, 5, 1], 
X = [1], 
Y = [3, 5, 1] ; 
L2 = [1, 5, 3, 5, 1], 
L1 = [1, 5, 3, 2, 1], 
X = [1, 5, 3], 
Y = [1] ; 
false. 
+0

こんにちはボリスを、 。あなたの答えは明確で整然としたものです。大変ありがとう! –

関連する問題