2015-04-24 128 views
3

給定一個列表的列表,我想用B s中的所有A替換,其中AB是序言變量。在另一個變量中替換一個變量

例如,如果該名單[[1,2,D,C],[A,D],[4,A],[1,2,A]] 我想要的結果是[[1,2,D,C],[B,D],[4,B],[1,2,B]]

爲此,我寫了下面,來替代所有的A S IN B S IN單列表:

/*substitude_single(+OldVar,+NewVar,+OldList,-NewList) */ 
substitute_single(_,_,[],[]). 
substitute_single(A,B,[A|As],[B|Bs]):- 
    substitute_single(A,B,As,Bs). 
substitute_single(A,B,[X|As],[X|Bs]):- 
    substitute_single(A,B,As,Bs). 

substitute(_,_,[],[]). 
substitute(A,B,[P|Ps],[Q|Qs]):- 
    substitute_single(A,B,P,Q), 
    substitute(A,B,Ps,Qs). 

現在我的主列表中的每個元素,這是一個列表本身上應用此

例如,當我在substitute_single(A,B,[C,A,D,1],X)上測試我的代碼時,出現了這個問題,我得到了很多解決方案,有些正在將值應用於變量。例如,我得到:

A = 1, 
C = 1, 
D = 1, 
X = [B, B, B, B] ; 

或:

A = D, 
C = D, 
X = [B, B, B, 1] 

,僅在許多其他的解決方案,我得到:

X = [C, B, D, 1] 

這是我想要的解決方案。然而,還有更多的解決方案(我不希望這樣)接踵而來。

所以我試圖削減方案,以防止產生更多的解決方案:

substitute_single(A,B,[A|As],[B|Bs]):- 
    substitute_single(A,B,As,Bs), 
    !. 

但現在,我雖然只得到一個單一的解決方案,這是不是我的目的了!

(對於上面的例子,該解決方案我得到的是

A = 1, 
C = 1, 
D = 1, 
X = [B, B, B, B]. 

我不知道如何或在哪裏我應該改變我的程序,以便它只會給我我想要的解決方案?

(注:AB可能是變量或還常量,例如:substitute_single(A,3,[C,A,D,1],X))應該產生[C,3,D,1]

+0

我會盡快恩澤可以提供把賞金一個純粹的,單調的解決方案。 – false

+0

......確定 - 對於常見情況。 – false

+0

@repeat,我指'substitute_single/4'的意思是在'B'中替換'A',在單個列表中出現'A'的所有外觀。然後,我將它用於列表的列表,將其應用於每個列表。 – TheEmeritus

回答

3

解決方案的問題在於,您將術語統一應用爲平等測試,而您需要的是嚴格測試相同的術語,其中有==/2謂詞。

爲了在單個列表中交換兩個可能是變量的項,假設一個正確關閉的列表和一個模式+,?,? - 下面的謂詞是足夠

exchgterms([],_,_,[]). 
exchgterms([X|Xs],A,B,[C|Ys]) :- 
    (X == A -> C=B ; 
    (X == B -> C=A ; C=X)), 
    exchgterms(Xs,A,B,Ys). 

你可以從這裏開始解決您的問題,將其更改爲滿足您的需求,特別是如果你的謂語必須有不同的模式。

UPDATE

我改變了我的謂詞的名字來強調它也可以用於交換不屬於變量方面。

它應該清楚,就應更換substitute_single/4用的substitute/4的第二句話以不同的順序的參數,所以你所尋求的解決方案是

substitute(_,_,[],[]). 
substitute(A,B,[L|Ls],[R|Rs]) :- 
    exchgterms(L,A,B,R), 
    substitute(A,B,Ls,Rs). 

我勸你改變的參數的順序在substitute/4,以便第三個參數成爲第一個參數。在這種形式下,大多數Prolog系統會知道如果這個參數被實例化,就像這裏的情況一樣,這兩個子句是相互排斥的,這將有助於更高效的執行。

-2

嘗試增加X \ = B到你的第二句話:

substitute_single(A,B,[X|As],[X|Bs]):- 
    X \= B, 
    substitute_single(A,B,As,Bs). 

使當X不是B時,它不會轉移到新的解決方案。

+0

我做過了,但現在變成了'[B,B,B,B]'解決方案。無論如何,我不認爲增加這條規則會給我我想要的。我的意思是,假設'X = A'(和'A≠B'),所以我不希望我的解決方案(替換後)也包含'A',我希望它具有'B'。 – TheEmeritus

+0

問題似乎出現在您的測試案例中。 Prolog將大寫輸入視爲變量。當用'substitute_single(A,B,[C,A,D,1],X)'測試它時,Prolog將C,A和D看作變量並試圖給出它們的值, 。嘗試使用像substitute_single(a,b,[c,a,d,1],X)這樣的小字母開頭的原子,或者將輸入放在單個括號中,例如substitute_single('A','B',[ C','A','D',1],X)。' – drippingtap

+0

單括號 - >單引號 – drippingtap

1

substVarInTerm/4是我想出的。

:- use_module(library(apply)). 

substVarInTerm(A,B,Term0,Term) :- 
    term_variables(Term0,Vars0), 
    exclude(==(A),Vars0,Vars), 
    copy_term(A^Vars^Term0,B^Vars^Term). 

注意substVarInTerm/4工作,如果第一個參數是其他東西比一個變量。

其他用例你給制定得罰款

?- substVarInTerm(A,B,[[1,2,D,C],[A,D],[4,A],[1,2,A]],R). 
R = [[1, 2, D, C], [B, D], [4, B], [1, 2, B]]. 

?- substVarInTerm(A,B,[C,A,D,1],X). 
X = [C, B, D, 1]. 

?- substVarInTerm(A,3,[C,A,D,1],X). 
X = [C, 3, D, 1]. 
+0

如果第一個參數必須是一個變量,那麼您的解決方案不會在問題末尾註釋說明第一個和第二個參數可以是非變量。 – migfilg

相關問題