2009-11-20 55 views
1

/*如果列表Ys是列表Xs中所有X出現的結果,則替換(X,Y,Xs,Ys)爲真。替換爲嵌套列表(序言)

這是我到目前爲止有:

subs(_,_,[],[]). 
subs(X,Y,[X|L1],[Y|L2]):- subs(X,Y,L1,L2). 
subs(X,Y,[H|L1],[H|L2]):- X\=H, not(H=[_|_]), subs(X,Y,L1,L2). 
subs(X,Y,[H|_],[L2]):- X\=H, H=[_|_], subs(X,Y,H,L2). 

我的代碼工作,除了它忽略了下面的嵌套列表中的元素。例如:

?- subs(a,b,[a,[a,c],a],Z). 
Z = [b, [b, c]] . 

我應該在該程序中添加什麼?

+0

事實證明,這是家常便飯rk:http://www.cs.toronto.edu/~yilan/324f09/324f09a4.pdf下次,**請**標記爲這樣! – Stephan202 2009-12-03 23:42:08

回答

1

問題是,一旦你找到一個嵌套列表,你忘記了後面的那個嵌套列表。相反,在使用嵌套嵌套進行遞歸之後,只需像以前一樣繼續。因此,你應該改變過去的條款如下:

subs(X,Y,[H|L1],[H2|L2]):- X\=H, H=[_|_], subs(X,Y,H,H2), subs(X, Y, L1, L2). 

除此之外,有一對夫婦的方法,使您可以提高代碼:

  1. 使用cuts!/0)至停止回溯。這樣你就不必重複自己。
  2. 您可以使用is_list/1來測試參數是否爲列表。
  3. 可以使用更多的空間。真。

因此,另一種解決方案是(現在用的\+/1代替not/1):

subs(_, _, [], []). 
subs(X, Y, [X|T1], [Y|T2]) :- subs(X, Y, T1, T2), !. 
subs(X, Y, [H|T1], [H|T2]) :- \+ is_list(H), subs(X, Y, T1, T2), !. 
subs(X, Y, [H1|T1], [H2|T2]) :- subs(X, Y, H1, H2), subs(X, Y, T1, T2). 

示範:

?- subs(a, b, [a, [a, [d, f, a]], a, b, a, [g]], Z). 
Z = [b, [b, [d, f, b]], b, b, b, [g]]. 
+0

明白了!謝謝!! – linda 2009-11-20 15:37:11

+0

削減是醜陋的,它們隱藏了以下條款中的隱含否定。我發現使用(... - > ...; ...)更好,這類似於函數式編程中的if-then-else。 – starblue 2009-11-20 20:25:59

+0

@starblue:是的,我隱約記得有切割問題(最近我重新獲得了對Prolog的興趣)。我會在不久的將來閱讀它。感謝您的支持,我會加倍努力:) – Stephan202 2009-11-21 15:13:29

2

這裏是你如何能使用它寫(... - > ...; ...):

subs(_, _, [], []). 
subs(X, Y, [H1|T1], [H2|T2]) :- 
    (H1 == X -> 
     H2 = Y 
    ; is_list(H1) -> 
     subs(X, Y, H1, H2), 
     subs(X, Y, T1, T2) 
    ; 
     H1 = H2, 
     subs(X, Y, T1, T2) 
    ).