为列表中的每个元素添加数字

时间:2014-11-04 07:46:14

标签: 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).

当我尝试运行查询时,它失败了。 任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

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

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

虽然没有相互递归。

您的istree/1 / istree/2代码非常广泛。我不会非常担心这两个条款,除非你向@PauloMoura表示你认为代码"工作正常"实际上它什么都没做。它会接受任何东西而不产生任何绑定。来自Prolog的有关单例变量的错误消息应视为 dire,严重错误必须才能解决。尝试使用istree/1谓词跟踪逻辑。 HF之间没有任何关系。 Prolog会说yes因为istree(_,F)成功通过调用isforest(F)然后绑定F = [],但这会被istree/1抛回,因为H之间没有任何关系{1}}和F。仔细考虑一下。没有办法,#34;工作正常" - 根本不做任何事情。您可以将其替换为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).

答案 1 :(得分: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]只是序言的句法糖{{1惯例是'.'(Head,Tail)是空列表(Tail)或另一个非空列表。

但是,您可能希望对列表进行显式测试,因为我怀疑许多(大多数?)prolog有特殊的列表实现,以便提高性能。

如果您想将[]限制为仅列表,则可以执行以下操作: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! 是SWI Prolog的内置谓词。如果你的序言没有,你可以自己动手。这是两个实现。

这是列表性的详尽测试。它验证列表的整个递归定义:列表是原子is_list/1或非空列表[],其中[H|T]本身就是一个列表。这是SWI Prolog使用的实现:

T

应该注意,对于长列表,这可能是一个有点昂贵的操作,因为它需要遍历整个列表。为此,您可能希望使用仅查看最顶层术语的更简单的测试:

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