在 SWI-Prolog 中填写列表 [英] Fill list in SWI-Prolog
问题描述
我正在尝试用数字 1、2、3、...、N 填充给定长度 N 的列表.
I am trying to fill a list of given length N with numbers 1,2,3,...,N.
我认为可以这样做:
create_list(N,L) :-
length(L,N),
forall(between(1,N,X), nth1(X,L,X)).
但是,这似乎不起作用.谁能说我做错了什么?
However, this does not seem to work. Can anyone say what I am doing wrong?
推荐答案
首先:使用 clpfd!
First things first: Use clpfd!
:- use_module(library(clpfd)).
在下面我介绍 zs_between_and/3
,它(与我之前的答案相比)提供了更多功能.
In the following I present zs_between_and/3
, which (in comparison to my previous answer) offers some more features.
首先,让我们先定义一些辅助谓词!
For a start, let's define some auxiliary predicates first!
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
的图片:
Let's run a few queries to get a picture of 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].
到目前为止,一切都很好...继续实际的填充列表"谓词zs_between_and/3
:
So far, so good... moving on to the actual "fill list" predicate 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).
有点巴洛克风格,我必须承认...
A bit baroque, I must confess...
让我们看看获得了哪些功能——与我的上一个答案相比!
Let's see what features were gained---in comparison to my 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].
想要更多?我们开始吧!
Want some more? Here we go!
?- 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
这篇关于在 SWI-Prolog 中填写列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!