嗯,你已经写好了解决方案!
这是一个“失败驱动的循环”。
Prolog 的行为就像有一个光标从左向右移动(好吧,这里是从上到下,由于格式化)通过该行,当谓词调用失败时,光标被发送回左侧,并弹回在repeat/0 右侧:
do(X) :- % X will take on the value of success
repeat , % The cursor bounces off here
% ...to try again!
format("Now trying something\n",[]) ,
random(0.0,1.0,X) , % Try something
format("Obtained ~q\n",[X]) ,
X < 0.2 , % Test whether success
format("Done!\n"). % On success, we end up here.
% On failure, we redo in order
% Redo X < 0.5 - There is no redo here
% Redo format/2 - There is no redo here
% Redo random/3 - There is no redo here
% Redo format/2 - There is no redo here
% Redo repeat/1 - Redo means cursor bounce
所以:
?- do(X).
Now trying something
Obtained 0.9837293974501616
Now trying something
Obtained 0.7031039796418066
Now trying something
Obtained 0.5838475489280747
Now trying something
Obtained 0.7179787440277113
Now trying something
Obtained 0.14040275695848495
Done!
X = 0.14040275695848495
由于没有“cut”,Prolog 顶层会询问您是否需要更多解决方案。如果您输入;,该过程将继续,在format("Done!\n") 重新输入。
这是一个替代方案
- 使用
between/3 最多尝试 4 次
- 在第一次成功时,使用“!”切断进一步的解决方案/重试,因此永远不会要求用户进行第二次尝试。
do(X) :-
between(1,4,K) ,
format("Now trying something, K = ~q\n",[K]) ,
random(0.0,1.0,X) ,
format("Obtained ~q\n",[X]) ,
X < 0.2 ,
format("Done!\n"),
!.
由于between/3 的“重做限制”性质,这实际上可能在有限数量的重做后失败:
?- do(X).
Now trying something, K = 1
Obtained 0.823698968756448
Now trying something, K = 2
Obtained 0.8617406555236128
Now trying something, K = 3
Obtained 0.7718447437621774
Now trying something, K = 4
Obtained 0.6010951752269867
false.
奖励脑筋急转弯
当“光标向左移动”时,这个谓词也会打印一些东西。
它的工作原理可能并不直接明显。
do(X) :-
between(1,4,K) ,
(true ; (format("Going to hit between/3 coming from the 'right' with K = ~q\n",[K]),fail) ),
format("Now trying something, K = ~q\n",[K]) ,
random(0.0,1.0,X) ,
format("Obtained ~q\n",[X]) ,
(true ; (format("NOPE! ~q doesn't cut it\n",[X]),fail) ),
X < 0.2,
format("Done!\n"),
!.
样本输出:
?- do(X).
Now trying something, K = 1
Obtained 0.25501790245795947
NOPE! 0.25501790245795947 doesn't cut it
Going to hit between/3 coming from the 'right' with K = 1
Now trying something, K = 2
Obtained 0.2778042792426882
NOPE! 0.2778042792426882 doesn't cut it
Going to hit between/3 coming from the 'right' with K = 2
Now trying something, K = 3
Obtained 0.042750567384520134
Done!
X = 0.042750567384520134.