【问题标题】:Creating [1,2,3...,N] list in Prolog在 Prolog 中创建 [1,2,3...,N] 列表
【发布时间】:2018-03-05 15:32:29
【问题描述】:

我想创建一个谓词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 会尝试寻找该谓词的另一个答案,即使它不存在。

【问题讨论】:

标签: list prolog


【解决方案1】:

我们看看第一次查询成功后的tracer:

?- 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)。所以你只需要在做Fnext is F+1之前添加F < N。所以: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

然后,如果您需要返回一个空列表,您可以添加一个谓词来轻松处理这种情况......顺便检查一下@repeat 在 cmets 中链接的问题

【讨论】:

  • 非常感谢您的回答!我对 Prolog 很陌生,它对我帮助很大!
猜你喜欢
  • 2019-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-11
  • 1970-01-01
  • 1970-01-01
  • 2020-12-22
相关资源
最近更新 更多