SWI-Prolog中的填写清单

时间:2011-07-22 16:00:46

标签: list prolog

我正在尝试用数字1,2,3,...,N填充给定长度N的列表。

我认为这可以这样做:

create_list(N,L) :-
    length(L,N),
    forall(between(1,N,X), nth1(X,L,X)).

但是,这似乎不起作用。谁能说我做错了什么?

3 个答案:

答案 0 :(得分:1)

我现在没有可用的prolog翻译,但不会像...那样......

  isListTo(N, L) :- reverse(R, L), isListFrom(N, R).
  isListFrom(0, []).
  isListFrom(N, [H|T]) :- M is N - 1, N is H, isListFrom(M, T).

反转可以通过使用例如http://www.webeks.net/prolog/prolog-reverse-list-function.html

所以跟踪isListTo(5,[1,2,3,4,5])......

  isListTo(5, [1, 2, 3, 4, 5])
  <=> isListFrom(5, [5, 4, 3, 2, 1])
  <=> 5 is 5 and isListFrom(4, [4, 3, 2, 1])
  <=> 4 is 4 and isListFrom(3, [3, 2, 1])
  <=> 3 is 3 and isListFrom(2, [2, 1])
  <=> 2 is 2 and isListFrom(1, [1])
  <=> 1 is 1 and isListFrom(0, [])
  QED

由于PROLOG不仅会评估真相,而且会找到令人满意的解决方案,因此这应该有效。我知道这是一个与你正在尝试的方法截然不同的方法,如果你的问题是专门关于在PROLOG中做循环的话,请道歉(如果是这种情况,可能会重新标记问题?)。

答案 1 :(得分:1)

首先要做的事情:使用

:- use_module(library(clpfd)).

在下面我提出的zs_between_and/3,(与我之前的回答相比)提供了更多功能。

首先,让我们先定义一些辅助谓词!

equidistant_stride([]    ,_).
equidistant_stride([Z|Zs],D) :-
   equidistant_prev_stride(Zs,Z,D).

equidistant_prev_stride([]     ,_ ,_).     % internal predicate
equidistant_prev_stride([Z1|Zs],Z0,D) :-
   Z1 #= Z0+D,
   equidistant_prev_stride(Zs,Z1,D).

让我们运行一些查询来获取equidistant_stride/2

的图片
?- Zs = [_,_,_], equidistant_stride(Zs,D).
Zs = [_A,_B,_C], _A+D#=_B, _B+D#=_C.

?- Zs = [1,_,_], equidistant_stride(Zs,D).
Zs = [1,_B,_C], _B+D#=_C, 1+D#=_B.

?- Zs = [1,_,_], equidistant_stride(Zs,10).
Zs = [1,11,21].

到目前为止,非常好......转到实际的#34;填充列表&#34;谓词zs_between_and/3

zs_between_and([Z0|Zs],Z0,Z1) :-
   Step in -1..1,
   Z0 #= Z1 #<==> Step #=  0,
   Z0 #< Z1 #<==> Step #=  1,
   Z0 #> Z1 #<==> Step #= -1,
   N #= abs(Z1-Z0),    
   (  fd_size(N,sup)
   -> true
   ;  labeling([enum,up],[N])
   ),
   length(Zs,N),
   labeling([enum,down],[Step]),
   equidistant_prev_stride(Zs,Z0,Step).

有点巴洛克式,我必须承认......

与我的previous answer相比,让我们看看获得了哪些功能!

?- zs_between_and(Zs,1,4).      % ascending  consecutive integers
Zs = [1,2,3,4].                 % (succeeds deterministically)

?- zs_between_and(Zs,3,1).      % descending consecutive integers (NEW)
Zs = [3,2,1].                   % (succeeds deterministically)

?- zs_between_and(Zs,L,10).     % enumerates fairly
  L = 10, Zs =       [10]       % both ascending and descenting (NEW)
; L =  9, Zs =     [9,10]
; L = 11, Zs =    [11,10]
; L =  8, Zs =   [8,9,10]
; L = 12, Zs = [12,11,10]
; L =  7, Zs = [7,8,9,10]
...

?- L in 1..3, zs_between_and(Zs,L,6).
  L = 3, Zs =     [3,4,5,6]
; L = 2, Zs =   [2,3,4,5,6]
; L = 1, Zs = [1,2,3,4,5,6].

想要更多?我们走了!

?- zs_between_and([1,2,3],From,To).
  From = 1, To = 3
; false.

?- zs_between_and([A,2,C],From,To).
  A = 1, From = 1, C = 3, To = 3    % ascending
; A = 3, From = 3, C = 1, To = 1.   % descending

答案 2 :(得分:1)

如果我理解正确,内置的谓词numlist / 3就可以了。 http://www.swi-prolog.org/pldoc/man?predicate=numlist/3