mapgiordani
mapgiordani

Reputation: 65

prolog - generate list with random values

I am trying to generate a list with random values between 1 and 10, but when I run the code, I'm receiving "false"...

geraL(0,_).
geraL(C,Y):-
  C is C-1,
  random(1,10,U),
  Y = [U|Y],
  geraL(C,Y).


?-geraL(13,X).

Upvotes: 1

Views: 6802

Answers (3)

repeat
repeat

Reputation: 18726

No need to write recursive code!

Simply use random/3, length/2, and maplist/2 like so:

?- length(Zs, 13), maplist(random(0,10), Zs).
Zs = [8, 9, 3, 5, 0, 7, 6, 7, 9, 9, 2, 4, 7].

?- length(Zs, 13), maplist(random(0,10), Zs).
Zs = [1, 7, 7, 6, 2, 5, 2, 9, 9, 2, 0, 7, 1].

?- length(Zs, 13), maplist(random(0,10), Zs).
Zs = [4, 6, 7, 0, 1, 3, 4, 9, 0, 8, 3, 8, 5].

?- length(Zs, 13), maplist(random(0,10), Zs).
Zs = [3, 1, 2, 1, 5, 3, 9, 8, 3, 7, 8, 1, 7].

Note the impurity! We get different answers—at least, most of the time...

For reproducible results, write down the actual method and its initial state, .

Upvotes: 4

SQB
SQB

Reputation: 4078

There is a built-in predicate findnsols/4 which finds at most N solutions.

This predicate can be used for the equivalent of a loop. Since random/3 is deterministic, we need to add repeat/0 to the goal to make it repeat.

geraL(C, Y) :- findnsols(C, U, (repeat, random(1, 10, U)), Y).

Also, please note that random/3 has been deprecated in SWI Prolog; it is advised to use random/1 or random_between/3 instead.
Most notably, random/3 excludes the upper bound, so random(1, 10, U) will never yield U = 10.

Upvotes: 1

lurker
lurker

Reputation: 58304

We'll cover each issue individually:

  • geraL(0, _) says that if you want zero random numbers, anything could be the result. I'm sure that's not what you mean. What should the result be if the number of elements is 0?

  • You should have a constraint that says C > 0 in your general case to avoid executing this rule when it's not desired

  • C is C - 1 will always fail because for any value of C, C and C-1 can never be the same value. You cannot reinstantiate a variable once it has a value within a predicate clause, except through backtracking.

  • Although Y = [U|Y] is allowed, it's a cyclical list definition (a list defined in terms of itself with an additional head element), and I'm sure that's not what you want, either.

If you fix these items, your program will work. The first two are fixed by using an auxiliary (different) variable. The last one is defining the base case correctly to associate the empty list with 0, not an anonymous variable.

geraL(0, []).   % Fix for item 1: zero values should be an empty list
geraL(C, Y):-
  C > 0,        % Fix for item 2
  C1 is C-1,    % Fix for item 3: use C1 for the new value
  random(1, 10, U),
  Y = [U|T],    % Fix for item 4: use T for the new value (tail)
  geraL(C1, T).

Upvotes: 2

Related Questions