我是Prolog的新手,我想写一个函数来找到一个遵循某些规则的列表。更具体地说,给定两个数字N和K,我想让我的函数找到一个列表,其中有K个2的幂,它们的和是N。例如,如果N=13,K=5,我希望我的列表是[2,2,1],其中第一个2表示两个4,第二个2表示两个2,第三个1表示一个1(4+4+2+2+1=13)。考虑到从列表的末尾开始,每个位置i代表2^i的2次方,所以我写了这样的代码。
sum2(List, SUM, N) :-
List = [] -> N=SUM;
List = [H|T],
length(T, L),
NewSUM is SUM + (H * 2**L),
sum2(T, NewSUM, N).
powers2(N,K,X):-
sum2(X,0,N),
sum_list(X, L),
K = L.
问题是:
?- sum2([2,2,1],0,13).
true.
?- sum2([2,2,1],0,X).
X = 13.
?- sum2(X,0,13).
false.
?- powers2(X,5,[2,2,1]).
X = 13.
?- powers2(13,5,[2,2,1]).
true.
?- powers2(13,X,[2,2,1]).
X = 5.
?- powers2(13,5,X).
false.
在这些情况下,X代表列表 我希望输出的是一个遵循规则的列表,而不是虚假的。你能帮助我找到如何解决这个问题,并在这些情况下有一个列表的输出?
你的谓词在非约束列表中失败的直接原因是由于你使用了 ->
控制流的构造。
这是一个简化的版本,你要做的是一个用于检查列表是否为空的小谓词。
empty_or_not(List, Answer) :-
( List = []
-> Answer = empty
; List = [H|T],
Answer = head_tail(H, T) ).
(附注: 确切的布局是一个品味问题, 但你应该把它作为一个小的前提条件. 始终 如果您使用的是 ;
运营商。我也敦促你 从来没有 把 ;
在线条的末端,而是在一个真正突出的位置。使用 ;
在Prolog中确实是个特例,如果它的格式太类似于 ,
这很难看出它的存在,也很难看出它适用于句子的哪些部分)。)
这似乎是可行的,对吗?
?- empty_or_not([], Answer).
Answer = empty.
?- empty_or_not([1, 2, 3], Answer).
Answer = head_tail(1, [2, 3]).
好吧,到目前为止,但如果我们用一个未绑定的列表来调用这个函数呢?
?- empty_or_not(List, Answer).
List = [],
Answer = empty.
突然间只有空列表被接受了,虽然我们 知道 从上面来看,非空列表也是可以的。
这是因为 ->
一旦发现其条件得到满足,就会切断任何替代方案。在最后一个例子中: List
是一个变量,所以它与 []
. 状况 List = []
会成功 List
到 []
),另一种是 List = [H|T]
不会去尝试。看似简单,但 ->
是Prolog的一个高级功能。它只应该由更有经验的用户来使用,因为他们知道他们真的不需要探索替代方案。
在Prolog中,通常,也是正确的,实现反结的方式是为不同的情况使用不同的子句。
empty_or_not([], empty).
empty_or_not([H|T], head_tail(H, T)).
现在这样做是符合逻辑的
?- empty_or_not([], Answer).
Answer = empty.
?- empty_or_not([1, 2, 3], Answer).
Answer = head_tail(1, [2, 3]).
?- empty_or_not(List, Answer).
List = [],
Answer = empty ;
List = [_2040|_2042],
Answer = head_tail(_2040, _2042).
相应地,你的定义是 sum2
应该更像这样。
sum2([], SUM, N) :-
N = SUM.
sum2([H|T], SUM, N) :-
length(T, L),
NewSUM is SUM + (H * 2**L),
sum2(T, NewSUM, N).
然而,这只是一小步
?- sum2(X, 0, 13).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [9] _2416 is 0+_2428* ...
ERROR: [8] sum2([_2462],0,13) at /home/gergo/sum.pl:5
ERROR: [7] <user>
你是在尝试对 H
,它没有值。如果你想使用 "普通 "的Prolog算术,你将需要枚举适当的值,这些值就是 H
在你尝试对其进行运算之前,可能会有。另外,你也可以使用算术约束。查看这两种方法的可能实现 Prolog中的算术学,用2的幂来表示一个数字.