Prolog: How to select biggest value from a set of random numbers
OK, the question is a bit poorly worded, but what I want to do is to select N numbers between 0 and MAX using rand_int and choose the largest value.
This is how I'm attempting this, but for some reason it doesn't work:
rand_val(Count, Rng, Res) :-
Count > 0,
Count is Count - 1,
rand_int(Rng, X),
Res is max(X, Res),
rand_val(Count, Rng, Res).
?- rand_val(2,100,Res).
-> no.
I'm a total newbie with Prolog (been stu开发者_高级运维dying it for just a few hours) so I'm probably just misunderstanding something.
Your problem is that you cannot instantiate a variable which is already instantiated with a different term. Thus, if Count is already instantiated (say with 2) you cannot do Count is Count - 1.
The is/2 operator needs the left variable to be uninstantiated (or instantiated with the actual value of the expression) and the right expression to be fully evaluated. The same applies to the recursive call. Once Res is instantiated to an integer you cannot change its value to another integer.
Here goes another implementation:
rand_val(Count, Rng, Res):-
rand_val(Count, Rng, -1, Res).
rand_val(0, _, Value, Value):-
!,
Value >= 0.
rand_val(Count, Rng, MValue, Value) :-
succ(NCount, Count),
X is random(Rng), %rand_int(Rng, X),
NValue is max(X, MValue),
rand_val(NCount, Rng, NValue, Value).
First note that I wrote two predicates rand_val/3 and rand_val/4. The former is the one with the signature you want. The latter has one more argument which will hold the maximum value found at that moment.
The first predicate just calls the rand_val/4 assigning a value -1 as the maximum found.
Now the first clause of rand_val/4 checks whether its input argument "Count" is 0. In that case it forbids backtracking (using the cut) and checks whether Value is a valid value. If it is < 0 the it's because you called rand_val/3 with Count = 0, so it really never issued a random number.
If it is > 0 the it just unifies the third and fourth argument (note that the fourth argument is the value you are expecting as output).
Now to the second clause: First it does a succ(NCount, Count) where NCount is a fresh variable. It will be instantiated with the predecessor of Count (Count-1).
Then we compute a random number. I am using SWI prolog so I call random(Max) to get the random number. This instantiates the fresh variable X with it.
At this point we have the select the largest value between the intermediate result (MValue) and X.
Finally we do the recursive step, now calling rand_val/4 with the new computed values NCount and NValue.
Note that the variable Value is instantiated when we return from the recursion (it gets bound in the first clause of rand_val/4).
My Prolog is rusty, so I may have missed something, however an obvious issue in your code is this: Count is Count - 1
.
What you written is an equation (as in maths) x = x - 1
. Obviously, this equation has no solutions. That's what Prolog engine means by its "No". You might try to rewrite it as NextCount is Count - 1
(and use NextCount instead of Count later on).
精彩评论