我是Prolog的新手,我试图编写简单的生成器,找到低于5的整数。
gen(0).
gen(X):- X<5
当我使用gen(X)运行程序时,它只打印X = 0并提示我输入内容,当我按下输入&#39;? - &#39;再次显示。
如何让他生成从零到五的数字?我正在使用SWI-Prolog。感谢
答案 0 :(得分:4)
如果您不想使用between/3
,可以使用辅助程序gen/3
轻松编写您的生成器:
gen(Num):-
gen(0, 5, Num).
gen(Cur, Top, Cur):- Cur < Top.
gen(Cur, Top, Next):-
Cur < Top,
succ(Cur, Cur1), % or Cur1 is Cur+1
gen(Cur1, Top, Next).
辅助程序gen/3
跟踪生成的当前数字和最高数字,并将第三个参数与当前生成的数字绑定。
gen/3
的第一个子句成功,当输入数字低于顶部时,将输出数字与输入数字绑定。
第二个子句递增当前数字,并递归调用自身以在回溯时获得下一个数字。
答案 1 :(得分:3)
用于枚举整数的内置谓词介于(低,高,数字)之间。
使用它你会写gen(X) :- between(0,4,X).
我以这种方式重新实现了
gen(X) :- between_(0, 4, X).
/* between_(I,J,K) is true if K is an integer between I and J inclusive. */
between_(I,J,I) :- I =< J.
between_(I,J,K) :- I < J, I1 is I+1, between_(I1,J,K).
问题的有趣部分是理解为什么只有一个参数的天真实现永远循环......
gen(0).
gen(X) :- gen(Y), X is Y + 1, X < 5.
?- gen(X).
X = 0 ;
X = 1 ;
X = 2 ;
X = 3 ;
X = 4 ;
^CAction (h for help) ? goals
[374,153] 3<5
[374,152] gen(3)
[374,151] gen(_G1013)
[374,150] gen(_G1013)
[374,149] gen(_G1013)
答案 2 :(得分:2)
好吧,因为gen / 1应该生成从0到5的整数(从技术上讲,如果它是5以下的整数,我们也应该产生负数),你可以这样做:
gen(0).
gen(1).
gen(2).
gen(3).
gen(4).
gen(5).
技术上满足chack的限制xD
对于谓词gen/2
,其中第一个参数定义了我们可以执行的最大数量:
gen(N,R):-
N>0,
R is N-1.
gen(N,R):-
N>1,
NN is N-1,
gen(NN,R).
但这具有使用第一个参数的优点。避免第一种解决方案的规则的重新定义是,我们应该能够在不改变规则的情况下用其他数字替换每次出现的5,并且程序应该仍然有效;我们还应该补充一点,我们不能使用列表(除非它们只有1个元素)或tupples或基本上任何带有两个变量作为参数的术语以及任何类型的编码(例如2^X
* 3*Y
) 。灵感来自第一个项目:
gen(X):-
clause(g(_),_) ->
g(X) ; (generate(5),!, g(X)).
generate(-1):-
compile_predicates([g/1]).
generate(N):-
assert(g(N)),
NN is N-1,
generate(NN).
compile_predicates/1
只是为了提高速度;请注意,如果我们更改最大数量,我们应该重新启动VM。另一种选择是避免在致电g/1
之前编译retract_all(g(_))
并添加generate/1
。当然,显而易见的问题是它不是纯粹的序言,因为我们依赖于元谓词。
答案 3 :(得分:-1)
使用内置函数numlist
怎么样?
?- numlist(0,4,X).
X = [0, 1, 2, 3, 4].