2015-11-23 73 views
1

我的任務是寫謂詞subst(T,A,V,R)改變原子A的所有出現在表達T到原子V並且將結果呈現爲R序言,在表情變化原子

例如:

subst(object(one, two),one,three,R). //R=object(three,two). 
susbt(a+1,a,2,R). //R=2+1. 

它可以很容易與方法:我改變表達式中使用T=..L列出,然後我的L每個元素比較A,如果它們是相同的,我可以將其更改爲V。最後,我可以逆轉第一個動作(重新獲得表達式),但我不知道如何處理如下情況: subst((a+1)*(b+3),a,2,W)。 //?喜歡的東西T=..L開始

我可以得到[*,a+1,b+3],但現在如果我想改變a2,我無法檢查的L每個連續的項目,因爲他們中的一些並不簡單原子/數字。現在我的問題是,是否有任何內置的謂詞來檢查列表中的元素是否如下所示:a1等,但不是a+1?我的意思是如果我不想先檢查它是否是原子,那麼後來如果它不是。

或者也許有更簡單的方法來解決這個問題?

編輯1: 感謝您的意見。我至今:

subst(T,A,V,R):-T=..L,make_simple(L,L1),replace(L1,A,V,L2),to_exp(L2,R). 

make_simple([],[]). 
make_simple([H|T],[H|W]):-atom(H),make_simple(T,W),!. 
make_simple([H|T],[H|W]):-number(H),make_simple(T,W),!. 
make_simple([H|T],[W1|W2]):- \+atom(H),\+number(H),H=..H1,make_simple(H1,W1),make_simple(T,W2). 

replace([],_,_,[]). 
replace([A|T],A,V,[V|W]):- replace(T,A,V,W),!. 
replace([H|T],A,V,[H|W]):- H\=A,\+is_list(H),replace(T,A,V,W),!. 
replace([H|T],A,V,[W1|W2]):-H\=A, is_list(H),replace(H,A,V,W1),replace(T,A,V,W2),!. 

to_exp([],[]). 
to_exp([H|T],[H|W]):- \+is_list(H),to_exp(T,W),!. 
to_exp([H|T],[W1|W2]):- is_list(H), (what next?) 

不幸的是,我不知道如何把這些AP拼湊現在to_exp一部分。特別是當它像:

to_exp([*,[+,a,1],[-,3,b]]). 

甚至更​​糟:

to_exp([*,[+,[*,4,2],1],[-,3,b]]). 

我的意思是,如果外部列表的元素是一個列表,我不知道如何識別它的準確三個元素的列表,其中每個元素都是一個原子/數字。任何提示?:)

EDIT2

好吧,我被告知,它變得過於複雜。也許吧,但我是Prolog的新手,我只使用迄今爲止學到的工具/技術,因爲我應該完成的任務是以這種方式構建的。當然,必須有更簡單的方法,就像@mat所建議的那樣,但我至今尚未對difmaplist謂詞有所瞭解。這就是爲什麼我決定以這種方式繼續這一個。

我發現沒有必要單獨檢查​​和number。有atomic/1,如果一個術語是數字,原子或en空列表(因此@mat關於SWI-Prolog提到的問題似乎並不重要)返回true。在此之後,我已經改變了先前的謂詞和我已經完成to_exp爲:

subst(T,A,V,R):-T=..L,make_simple(L,L1),replace(L1,A,V,L2),to_exp(L2,R). 

make_simple([],[]). 
make_simple([H|T],[H|W]):-atomic(H),make_simple(T,W),!. 
make_simple([H|T],[W1|W2]):- \+atomic(H),H=..H1,make_simple(H1,W1),make_simple(T,W2),!. 

replace([],_,_,[]). 
replace([A|T],A,V,[V|W]):- replace(T,A,V,W),!. 
replace([H|T],A,V,[H|W]):- H\=A,\+is_list(H),replace(T,A,V,W),!. 
replace([H|T],A,V,[W1|W2]):-H\=A, is_list(H),replace(H,A,V,W1),replace(T,A,V,W2),!. 

to_exp([],[]). 
to_exp([Z,H1,H2],L):-atomic(H1),atomic(H2),L=..[Z,H1,H2],!. 
to_exp([Z,H1,H2],L):- \+atomic(H1),atomic(H2),to_exp(H1,W1),L=..[Z,W1,H2]. 
to_exp([Z,H1,H2],L):- atomic(H1),\+atomic(H2),to_exp(H2,W1),L=..[Z,H1,W1]. 
to_exp([Z,H1,H2],L):- \+atomic(H1),\+atomic(H2),to_exp(H1,W1),to_exp(H2,W2),L=..[Z,W1,W2]. 

現在,既適用函子和參數,簡單和嵌套的。 無論如何,感謝您的影響,我將來肯定會考慮使用difmaplist。歡呼:)

+2

你在正確的軌道上。你可以使用'atom/1':如果它的參數是一個原子,則爲真。注意:這是一個非單調謂詞,所以只有當參數被充分實例化時才使用它。例如,參見「原子(X)」,X =「與原子(X)」。 – mat

+1

爲什麼不使用'= ..'遞歸地分解它呢?所以'(a + 1)*(b + 3)'導致'[*,a + 1,b + 3]',並且每個元素都會導致'[*]',[+,a,1] '和'[+,b,3]'。在最底層,你可以找到你的原子來代替。你可以使用mat的想法來使用'atom'來知道你什麼時候「觸底」。如果'X'是一個數字,'number(X)'是真的。 – lurker

+0

您希望'subst(foo(a,b),foo,bar,R).'工作嗎?它應該失敗嗎?它應該用'R = foo(a,b)'成功嗎?還是應該用'R = bar(a,b)'成功? – lurker

回答

0

Altough,還有更有效的回答這個問題,我將在此一爲那些,誰在序言是begginners喜歡我,因爲它的使用非常基本的操作:

subst(T,A,V,R):-T=..L,make_simple(L,L1),replace(L1,A,V,L2),to_exp(L2,R). 

make_simple([],[]). 
make_simple([H|T],[H|W]):-atomic(H),make_simple(T,W),!. 
make_simple([H|T],[W1|W2]):- \+atomic(H),H=..H1,make_simple(H1,W1),make_simple(T,W2),!. 

replace([],_,_,[]). 
replace([A|T],A,V,[V|W]):- replace(T,A,V,W),!. 
replace([H|T],A,V,[H|W]):- H\=A,\+is_list(H),replace(T,A,V,W),!. 
replace([H|T],A,V,[W1|W2]):-H\=A, is_list(H),replace(H,A,V,W1),replace(T,A,V,W2),!. 

to_exp([],[]). 
to_exp([Z,H1,H2],L):-atomic(H1),atomic(H2),L=..[Z,H1,H2],!. 
to_exp([Z,H1,H2],L):- \+atomic(H1),atomic(H2),to_exp(H1,W1),L=..[Z,W1,H2]. 
to_exp([Z,H1,H2],L):- atomic(H1),\+atomic(H2),to_exp(H2,W1),L=..[Z,H1,W1]. 
to_exp([Z,H1,H2],L):- \+atomic(H1),\+atomic(H2),to_exp(H1,W1),to_exp(H2,W2),L=..[Z,W1,W2]. 
+0

在Prolog中的初學者就像你應該把它當作一個例子來解釋這個任務。相反,請考慮Prolog術語的完整規則結構,並使其更通用。例如,下面的查詢怎麼樣:'? - subst(f(a,b,c),a,2,R).'。它錯誤地**失敗**與您的代碼。它適用於我的解決方案。回想一下,還有Prolog術語沒有arity 2.另一個例子:'? - subst(f(a),a,2,R)''它**代碼失敗**。它適用於我發佈的解決方案。 – mat

2

請考慮到序言的完整規則。

substitution(A0, A0, A, A).  
substitution(T0, A0, A, T) :- 
     dif(T0, A0), 
     T0 =.. [F|Args0], 
     maplist(subst_(A0, A), Args0, Args), 
     T =.. [F|Args]. 

subst_(A0, A, T0, T) :- substitution(T0, A0, A, T). 

實例查詢及其結果:

?- substitution(a+b+[c,d,a], a, 2, R). 
R = 2+b+[c, d, 2] ; 
false.