如何在序言中模拟嵌套循环?
how can simulate nested loop in prolog?
如何在 Prolog 中模拟此代码?
// L = an existing list ;
// function foo(var X, var Y)
result = new List();
for(int i=0;i<L.length;i++)
for(int j=0;j<L.length;j++){
result.add(foo(L.get(i), L.get(j));
}
您可以轻松定义 forto/4
元谓词。一个例子,取自 Logtalk 库 loop
object:
:- meta_predicate(forto(*, *, *, 0)).
forto(Count, FirstExp, LastExp, Goal) :-
First is FirstExp,
Last is LastExp,
forto_aux(Count, First, Last, 1, Goal).
:- meta_predicate(forto_aux(*, *, *, *, 0)).
forto_aux(Count, First, Last, Increment, Goal) :-
( First =< Last ->
\+ \+ (Count = First, call(Goal)),
Next is First + Increment,
forto_aux(Count, Next, Last, Increment, Goal)
; true
).
示例目标:
?- loop::forto(I, 1, 2, loop::forto(J, 1, 3, (write(I-J), nl))).
1-1
1-2
1-3
2-1
2-2
2-3
true.
一些 Prolog 编译器还提供对 "logical loops" 的内置或库支持,具有良好的表达能力。示例是(按字母顺序排列)B-Prolog、ECLiPSe 和 SICStus Prolog。查看这些系统的文档以获取详细信息。如果您需要跨大多数 Prolog 系统的可移植解决方案,请查看 Logtalk 的库文档。或者简单地采用上面的示例并定义您自己的循环元谓词。
嵌套循环基本上是序列之间的连接,Prolog 中的大多数列表处理最好在没有索引的情况下表达:
?- L=[a,b,c], findall(foo(X,Y), (member(X,L),member(Y,L)), R).
L = [a, b, c],
R = [foo(a, a), foo(a, b), foo(a, c), foo(b, a), foo(b, b), foo(b, c), foo(c, a), foo(c, b), foo(..., ...)].
编辑
有时整数允许以简单的方式捕捉含义。例如,我的解决方案是针对 Prolog 上下文测验中较简单的一个。
icecream(N) :-
loop(N, top(N)),
left, loop(N+1, center), nl,
loop(N+1, bottom(N)).
:- meta_predicate loop(+, 1).
loop(XH, PR) :-
H is XH,
forall(between(1, H, I), call(PR, I)).
top(N, I) :-
left, spc(N-I+1), pop,
( I > 1
-> pop,
spc(2*(I-2)),
pcl
; true
),
pcl, nl.
bottom(N, I) :-
left, spc(I-1), put(\), spc(2*(N-I+1)), put(/), nl.
center(_) :- put(/), put(\).
left :- spc(4).
pop :- put(0'().
pcl :- put(0')).
spc(Ex) :- V is Ex, forall(between(1, V, _), put(0' )).
运行 在 SWI-Prolog 中:
?- icecream(3).
()
(())
(( ))
/\/\/\/\
\ /
\ /
\ /
\/
true.
?- forall(loop(3,[X]>>loop(2,{X}/[Y]>>writeln(X-Y))),true).
1-1
1-2
2-1
2-2
3-1
3-2
true.
您可以通过 SICStus-prolog 使用此谓词来循环变量 I,J
直到 N
并在事实中获取所有变量 foo/2
下面依次提到;
代码
loop(N) :- for(I,0,N),param(N) do
for(J,0,N),param(I) do
write(foo(I,J)),nl.
结果
| ?- loop(2).
foo(0,0)
foo(0,1)
foo(0,2)
foo(1,0)
foo(1,1)
foo(1,2)
foo(2,0)
foo(2,1)
foo(2,2)
yes
如何在 Prolog 中模拟此代码?
// L = an existing list ;
// function foo(var X, var Y)
result = new List();
for(int i=0;i<L.length;i++)
for(int j=0;j<L.length;j++){
result.add(foo(L.get(i), L.get(j));
}
您可以轻松定义 forto/4
元谓词。一个例子,取自 Logtalk 库 loop
object:
:- meta_predicate(forto(*, *, *, 0)).
forto(Count, FirstExp, LastExp, Goal) :-
First is FirstExp,
Last is LastExp,
forto_aux(Count, First, Last, 1, Goal).
:- meta_predicate(forto_aux(*, *, *, *, 0)).
forto_aux(Count, First, Last, Increment, Goal) :-
( First =< Last ->
\+ \+ (Count = First, call(Goal)),
Next is First + Increment,
forto_aux(Count, Next, Last, Increment, Goal)
; true
).
示例目标:
?- loop::forto(I, 1, 2, loop::forto(J, 1, 3, (write(I-J), nl))).
1-1
1-2
1-3
2-1
2-2
2-3
true.
一些 Prolog 编译器还提供对 "logical loops" 的内置或库支持,具有良好的表达能力。示例是(按字母顺序排列)B-Prolog、ECLiPSe 和 SICStus Prolog。查看这些系统的文档以获取详细信息。如果您需要跨大多数 Prolog 系统的可移植解决方案,请查看 Logtalk 的库文档。或者简单地采用上面的示例并定义您自己的循环元谓词。
嵌套循环基本上是序列之间的连接,Prolog 中的大多数列表处理最好在没有索引的情况下表达:
?- L=[a,b,c], findall(foo(X,Y), (member(X,L),member(Y,L)), R).
L = [a, b, c],
R = [foo(a, a), foo(a, b), foo(a, c), foo(b, a), foo(b, b), foo(b, c), foo(c, a), foo(c, b), foo(..., ...)].
编辑
有时整数允许以简单的方式捕捉含义。例如,我的解决方案是针对 Prolog 上下文测验中较简单的一个。
icecream(N) :-
loop(N, top(N)),
left, loop(N+1, center), nl,
loop(N+1, bottom(N)).
:- meta_predicate loop(+, 1).
loop(XH, PR) :-
H is XH,
forall(between(1, H, I), call(PR, I)).
top(N, I) :-
left, spc(N-I+1), pop,
( I > 1
-> pop,
spc(2*(I-2)),
pcl
; true
),
pcl, nl.
bottom(N, I) :-
left, spc(I-1), put(\), spc(2*(N-I+1)), put(/), nl.
center(_) :- put(/), put(\).
left :- spc(4).
pop :- put(0'().
pcl :- put(0')).
spc(Ex) :- V is Ex, forall(between(1, V, _), put(0' )).
运行 在 SWI-Prolog 中:
?- icecream(3).
()
(())
(( ))
/\/\/\/\
\ /
\ /
\ /
\/
true.
?- forall(loop(3,[X]>>loop(2,{X}/[Y]>>writeln(X-Y))),true).
1-1
1-2
2-1
2-2
3-1
3-2
true.
您可以通过 SICStus-prolog 使用此谓词来循环变量 I,J
直到 N
并在事实中获取所有变量 foo/2
下面依次提到;
代码
loop(N) :- for(I,0,N),param(N) do
for(J,0,N),param(I) do
write(foo(I,J)),nl.
结果
| ?- loop(2).
foo(0,0)
foo(0,1)
foo(0,2)
foo(1,0)
foo(1,1)
foo(1,2)
foo(2,0)
foo(2,1)
foo(2,2)
yes