1

I'm new to Prolog. I read this code which finds prime factors of an integer:

factors(1,[1]) :-
   true, !.
factors(X,[Factor1|T]) :-
   X > 0,
   between(2,X,Factor1), 
   NewX is X // Factor1, (X mod Factor1) =:= 0,
   factors(NewX,T), !.

And changed it to this one:

factors(1,[[1,1]]) :-
   true, !.
factors(X,[Factor1|T]) :-
   X > 0,
   (  is_list(Factor1),
      length(Factor1, 2),
      Factor1 = [Base|A],
      A = [Pow], 
      between(2,X,Base),
      between(1,100,Pow), 
      NewX is X / (Base ** Pow),
      (X mod Base) =:= 0,
      (NewX mod Base) =\= 0
   ),
   factors(NewX,T), !.

Well the first one works perfect, but the latter doesn't respond to queries. i.e. when I enter:

factors(2,[[2,1],[1,1]]).  

I get 'true', but when I enter:

factors(2,X).  

I get 'false'.

4

2 回答 2

2

当您输入factors(2,X)时,Factor1未绑定并is_list(Factor1)失败。

我认为你的代码

is_list(Factor1),
length(Factor1, 2),
Factor1 = [Base|A],
A = [Pow]

可以简写为Factor1 = [Base,Pow]。由于Factor1未在其他任何地方使用,因此您可以移至[Base,Pow]子句的开头。

可以省略true,这里没有影响。括号也没有任何效果。所以你的代码可以写成:

factors(1,[[1,1]]) :- !.
factors(X,[[Base,Pow]|T]) :-
   X > 0,
   between(2,X,Base),
   between(1,100,Pow), 
   NewX is X / (Base ** Pow),
   (X mod Base) =:= 0,
   (NewX mod Base) =\= 0,
   factors(NewX,T), !.

在我的系统上(使用 SICStus),必须使用

NewX is X // floor(Base ** Pow)

防止它变成一个浮点数,当作为参数NewX传递给它时会导致错误。mod

编辑:我最初写道,最后一次剪辑没有效果。这是不正确的,因为between/2创建了选择点。我删除了我的答案的那部分并将删减的内容放回代码中。

于 2014-05-15T08:21:50.010 回答
2

因为BaseandPow还没有绑定到任何东西(它们是X您传递的 的一部分),所以您无法计算NewX(并且betweens 也可能不起作用)。

于 2014-05-14T20:33:15.177 回答