在Prolog中创建[1,2,3 ...,N]列表
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Prolog中创建[1,2,3 ...,N]列表相关的知识,希望对你有一定的参考价值。
我想创建一个谓词arrayLEQ(L,N)
,这在L = [1,2,3,...,N]
时是真的。
我尝试递归地做:
arrayLEQ(L,N) :- arrayLEQ([],L,1,N).
arrayLEQ(L1,L2,N,N) :- append(L1,[N],L2).
arrayLEQ(L1,L2,F,N) :- Fnext is F+1, append(L1,[F],L1n), arrayLEQ(L1n,L2,Fnext,N).
起初我认为它会起作用,但遗憾的是它没有。
当我这样做:?- arrayLEQ(L,5)
我得到L = [1,2,3,4,5]
这是正确的答案,但Prolog准备寻找另一个答案,这是不想要的。
你是否介意向我解释我做错了什么以及为什么Prolog试图寻找这个谓词的另一个答案,即使它不存在。
答案
让我们看看第一个查询成功后的跟踪器:
?- arrayLEQ(L,5).
L = [1,2,3,4,5].
more
Redo:arrayLEQ([1, 2, 3, 4], _5040, 5, 5)
Call:_5844 is 5+1
Exit:6 is 5+1
Call:lists:append([1, 2, 3, 4], [5], _5854)
Exit:lists:append([1, 2, 3, 4], [5], [1, 2, 3, 4, 5])
Call:...
Call:_5880 is 6+1
Exit:7 is 6+1
Call:lists:append([1, 2, 3, 4, 5], [6], _5890)
Exit:lists:append([1, 2, 3, 4, 5], [6], [1, 2, 3, 4, 5, 6])
Call:arrayLEQ([1, 2, 3, 4, 5, 6], _5040, 7, 5)
Call:_5922 is 7+1
Exit:8 is 7+1
Call:lists:append([1, 2, 3, 4, 5, 6], [7], _5932)
Exit:lists:append([1, 2, 3, 4, 5, 6], [7], [1, 2, 3, 4, 5, 6, 7])
Call:arrayLEQ([1, 2, 3, 4, 5, 6, 7], _5040, 8, 5)
Call:_5970 is 8+1
Exit:9 is 8+1
and so on...
您可以看到您的程序不断添加元素到列表中,而不会停止。所以有两种解决方案:
- 添加切口(
!
):arrayLEQ(L1,L2,N,N):- !, append(L1,[N],L2).
它有效但可能(在我看来)有更好的解决方案。 - 添加元素时,不检查是否已经传递了所设置的阈值(在本例中为
5
)。所以你只需要在做F < N
之前添加Fnext is F+1
。所以:arrayLEQ(L1,L2,F,N) :- F < N, Fnext is F+1, append(L1,[F],L1n), arrayLEQ(L1n,L2,Fnext,N)
。 (我个人更喜欢这个解决方案)
所以查询现在(用第二个解决方案):
?- arrayLEQ(L,5).
L = [1, 2, 3, 4, 5].
more.
false.
我建议你不要使用append/3
,因为在这种情况下根本不需要写这样的东西:
orderedList(L,N):-
orderedList(L,1,N).
orderedList([N],N,N). %you can add a cut ! here, to avoid further search
orderedList([H|T],C,N):-
C < N,
H is C,
C1 is C+1,
orderedList(T,C1,N).
?- orderedList(L,5).
L = [1, 2, 3, 4, 5]
more
false
然后,如果你需要返回一个空列表,你可以添加一个谓词来轻松处理这个案例... BTW也检查@repeat在评论中链接的问题
以上是关于在Prolog中创建[1,2,3 ...,N]列表的主要内容,如果未能解决你的问题,请参考以下文章