Prolog 向列表中的每个元素添加编号

Prolog 向列表中的每个元素添加编号,prolog,Prolog,我试图给列表和子列表中的每个元素添加一个数字。列表还包含一个树。函子不能是数字,只有叶子可以是数字 % 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). 当我尝试运行查询时,它失败了。 任何帮助都将不胜感激。我喜欢istree/1和isfor

我试图给列表和子列表中的每个元素添加一个数字。列表还包含一个树。函子不能是数字,只有叶子可以是数字

% 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).
当我尝试运行查询时,它失败了。
任何帮助都将不胜感激。

我喜欢istree/1和isforest/1之间相互递归的想法。如果要强制执行该属性,可能需要以下代码:

istree([]).
istree([H|T]) :- 
   (number(H) ; istree(H)), 
   istree(T).
但这里没有相互递归

您的istree/1/istree/2代码非常离谱。我不会太担心这两个子句,除非您向@PauloMoura表示,您认为代码可以正常工作,而实际上它基本上什么都做不了。它将接受任何内容而不生成任何绑定。Prolog中关于单例变量的错误消息应该被视为可怕的关键错误,必须加以解决。尝试使用istree/1谓词按照逻辑进行操作。H和F之间没有关系。Prolog会说“是”,因为istree_F通过调用isforestF然后绑定F=[]成功,但这在istree/1中被丢弃,因为H和F之间没有关系。仔细想想。它不可能很好地工作,它根本不起任何作用。你可以用真的来代替它

您的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).

你的问题陈述是

我试图给列表和子列表中的每个元素添加一个数字。 该列表还包含一个树,函子不能是数字,只有叶子可以是数字

% 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).
你不会说你的树是如何表现的。然而,这是一个非常简单的遍历问题。您可以做一些非常普通的事情,例如,接受任何任意的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!
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!
您不需要对列表进行明确性测试,因为空列表只是原子“[]”,而非空列表[Head | Tail]只是序言中术语“.”Head,Tail的语法糖,按照惯例,Tail是空列表[]或另一个非空列表

然而,您可能需要对列表进行显式测试,因为我怀疑很多人都这么认为?序言有特殊的列表实现,以提高性能

如果您想将increment/3仅限于列表,您可以这样做,其中increment/3遍历一个列表,并将转换应用于其中的每个元素:

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!
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的内置谓词。如果你的序言没有一个,那么你可以自己写一个。这里有两个实现

这是对倦怠的详尽测试。它验证了列表的整个递归定义:列表是atom[]或非空列表[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

子句中有一个拼写错误istree:-istree,F。。您的Prolog系统可能在该子句中打印了一条关于单例变量的警告。我测试了这段代码,它工作正常。如果给定的项是多路树,它将显示为真。您能告诉我还有哪些地方可能出错。当然,它显示为真!您在第二个参数中使用变量调用istree/2谓词,这意味着使用变量参数调用isforest/1。是否有其他方法检查给定元素是否是列表中的树。