2014-11-04 83 views
-1

我試圖給列表和子列表中的每個元素添加一個數字。該列表還包含一棵樹(函子不能爲數字,只有葉子可以是數字)。將數字添加到列表中的每個元素

% Checking if element in a list is a tree 
istree(H) :- istree(_,F). 
istree(_,F) :- isforest(F). 
isforest([]). 
isforest([T|Ts]) :- istree(T), isforest(Ts). 

當我嘗試運行查詢失敗。 任何幫助,將不勝感激。

+3

有沒有在條款'istree(H)一個錯字: - istree(_,F).'。您的Prolog系統可能會在該子句中顯示關於單身變量的警告。 – 2014-11-04 11:54:28

+0

我測試了這段代碼,它工作正常。如果給定的術語是多路樹,那麼它就表示真實。可以告訴我哪裏可能會出錯。 – abc 2014-11-04 19:04:30

+0

當然它顯示真實!你在第二個參數中用一個變量調用'istree/2'謂詞,這意味着調用具有可變參數的'isforest/1'。 – 2014-11-04 19:21:33

回答

1

您的問題聲明

我嘗試了一些在列表和子列表添加到每個元素。 該列表還包含一棵樹(該函數不能是數字,只有葉子可以是數字)。

你不說如何你的「樹」來表示。但是,這是一個非常簡單的遍歷問題。你可以做一些非常通用的,這樣,將接受任意Prolog項,並增加中發現的所有號碼:

increment(X , Y , Z) :- number(X) , ! , Z is X+Y) . 
increment(X , Y , Z) :- var(X)  , ! , Z = X . 
increment(X , Y , Z) :- atomic(X) , ! . Z = X . % atomic terms, including the empty list, remain unchanged. 
increment(X , Y , Z) :- compound(X) , ! ,   % otherwise, we have a compound term, including a non-empty list... 
    X =.. [Functor|Args] ,       % - decompose the compound term into its functor and argument list 
    increment(Args,Y,Args1) ,       % - increment the argument list 
    Z =.. [Functor|Args1] ,       % - assemble the new, incremented compound term 
    .             % Easy! 

你並不真的需要列出明確地測試,空的名單只是原子'[]'而非空列表[Head|Tail]僅僅是序言詞'.'(Head,Tail)的語法糖,約定是Tail是空列表([])或另一個非空列表。

但是,你可能想要列表的明確測試,因爲我懷疑很多(大多數?)序言具有特殊的列表實現,以提高性能。

如果你想限制你increment/3只是列出,你可以做這樣的事情,在這裏increment/3遍歷一個列表,並變換應用於中發現的每一個元素:

increment([]  , _ , [] ) :- 
increment([X|Xs] , Y , [Z|Zs]) :- 
    transform(X ,Y , Z ) , 
    increment(Xs ,Y , Zs) 
    . 

transform(X,Y,Z) :- var(X)  , ! , Z = X . 
transform(X,Y,Z) :- number(X) , ! , Z is X+Y . 
transform(X,Y,Z) :- is_list(X) , ! , increment(X,Y,Z) . 
transform(X,Y,Z) :- atomic(X) , ! , Z = Z . 
transform(X,Y,Z) :- compound(X) , ! , 
    X =.. [F|As] ,  % - decompose the compound term into its functor and list of arguments 
    increment(As,Y,A1) , % - increment the argument list 
    Z =.. [F|A1]   % - assemble the incremented compount term 
    .     % Easy! 

is_list/1是一個內置SWI Prolog的謂詞。如果你的序言沒有一個,那麼推出你自己的代碼是微不足道的。這裏有兩個實現。

這是一個詳盡的列表測試。它驗證列表的整個遞歸定義:列表是原子[]或非空列表[H|T],其中T本身就是一個列表。這是SWI Prolog的使用的實現:

is_list( X ) :- var(X) , ! , fail . % variables are not lists 
is_list( [] ) .      % the empty list 
is_list([_|T]) :- is_list(T) .  % a non-empty list has a tail that is itself a list 

人們應該注意到,對於長的列表,因爲它需要遍歷整個列表,這可能是一個比較昂貴的操作。爲此,您可能需要使用一個簡單的測試,只有着眼於最上面的術語:

is_list( X ) :- var(X) , ! , fail . % variables are not lists 
is_list( [] ) .      % the empty list 
is_list( [_|_]) .      % a non-empty list 
1

我喜歡istree/1isforest/1之間的相互遞歸的想法。如果你想強制執行財產,你可能需要這樣的代碼:

istree([]). 
istree([H|T]) :- 
    (number(H) ; istree(H)), 
    istree(T). 

儘管這裏沒有相互遞歸。

你的istree/1/istree/2代碼是相當廣泛的標誌。除了你向@PauloMoura表明你認爲代碼「正常工作」的時候,我並不擔心這兩個條款,事實上它基本上什麼都不做。它會接受任何事物而不產生任何綁定。來自Prolog關於單例變量的錯誤消息應該被視爲可怕,嚴重錯誤其中必須被解決。嘗試並遵循邏輯與你的謂詞istree/1謂詞。 HF之間沒有關係。 Prolog將會說yes,因爲istree(_,F)通過調用isforest(F)並然後綁定F = []成功,但由於HF之間沒有關係,因此被丟棄。考慮一下。它沒有辦法「正常工作」 - 它根本沒有做任何事情。您可以用true替換它。

您的isforest/1看起來不錯,它只是假設有一個合法的istree/1來電。如果我想以配合相互遞歸的主題,我可以試試這個:

istree(E) :- number(E). 
istree([H|T]) :- isforest([H|T]). 

的這一切讓你非常接近,加入了一些到列表中的每個元素和子列表,你提到的是你的任務。我假設你的意思是算術上的,例如addToTree([1,[2],3], 3, [4,[5],6])會統一。要做到這一點我應該這樣做:

% base case: empty list 
addToTree([], _, []). 

% case 1: head is a number 
addToTree([H|T], N, [HN|Rest]) :- 
    number(H), 
    HN is H+N, 
    addToTree(T, N, Rest). 

% case 2: head is a list 
addToTree([H|T], N, [NH|Rest]) :- 
    is_list(H), 
    addToTree(H, N, NH), 
    addToTree(T, N, Rest). 
相關問題