1

I found that for swi-prolog it exists findnsols, however, it is not working for me.

My predicate generate_color(Color) generates random colors for .

When I try to call it N times and save the values ​​of the executions in a list I always get a single result instead of many.

findnsols(3, Color, generate_color(Color),Colors).

Colors = ["# 4c4b43"].

findnsols(3, Color, generate_color(Color),Colors).

Colors = ["# 158955"].

findnsols (300, Color, generate_color (Color), Colors).

Colors = ["# 5d67e1"].

Does anyone know of any way that I can get even the Nsolutions I want in a list?

Expected output:

findnsols(3, Color, generate_color(Color),Colors).

Colors = ["# 5d67e1", "# 4c4b43", "# 158955"].

false
  • 10,264
  • 13
  • 101
  • 209
Ruslan López
  • 4,433
  • 2
  • 26
  • 37

2 Answers2

2

I assume that generate_color only returns a single color (i.e., you cannot press ; after the first solution is given).

Thus, findnsols does not work, since it works based on backtracking, i.e., entering your Goal again and trying to find further solutions.

I suggest a solution similar to the following:

length(Colors, 10), maplist(generate_color, Colors).

This defines a list Colors of length 10, where all entries must correspond to generate_color (for more infos see maplist)


Related example:

random generates a single random number.

?- findnsols(3, N, random(0, 100, N), Rands).
Rands = [33].

?- length(Rands, 10), maplist(random(0,100), Rands).
Rands = [85, 92, 81, 66, 98, 15, 74, 95, 56|...].
Markus Weninger
  • 11,931
  • 7
  • 64
  • 137
  • 1
    worked like a charm! you can try to solve the exercise yourself, your answer was for the unit tests: https://www.codewars.com/kata/56f1c6034d0c330e4a001059/prolog – Ruslan López Jun 24 '21 at 06:33
1

To have a predicate that generates multiple random colors, its not enough to do:
(the 0x syntax is from ISO core standard, an integer notation in base 16)

generate_color(Color) :-
   random(0, 0xFFFFFF, Color).

If you call the above, it only generates one solution:
(not to be used in the browser, just integer in base 10 shown)

?- generate_color(Color).
Color = 8649520.

If you want to make an infinite generator, you have to place repeat/0:

generate_color(Color) :-
   repeat,
   random(0, 0xFFFFFF, Color).

It then works as follows:

?- generate_color(Color).
Color = 4282662 ;
Color = 13523844 ;
Color = 511176 ;
Etc..

Instead of using repeat/0, you can also program generate_color/1
tail recursive to have it return multiple solutions.

Edit 04.09.2021:
In SWI-Prolog you can use format/2 to convert to base 16,
to get something that can be then used inside the browser:

?- generate_color(Color), format('#~|~`0t~16r~6+', [Color]).
#415926
C = 4282662 ;
#ce5b84
C = 13523844 ;
#07ccc8
C = 511176.
Etc..
  • interesting solution however those colors are not valid html color. you can verify it at https://www.codewars.com/kata/56f1c6034d0c330e4a001059/prolog – Ruslan López Sep 04 '21 at 15:32
  • You have to convert the decimal number into a hex number with 6 hex digits. See the 4 nibbles example in the comment section here https://www.swi-prolog.org/pldoc/man?predicate=format/2 –  Sep 04 '21 at 16:16
  • however that produes problems when trying to pass regex based unit tests: `generate_color(Color) :-repeat,random(0, 0xFFFFFF, AColor),Color = [AColor],format('#~|~`0t~16r~6+', Color).` atom_chars/2: Type error: `atom' expected, found `[14906927]' (a list) – Ruslan López Sep 04 '21 at 21:57
  • You need to use format/3 (the termary predicate) to obtain some resut and not have it written on the output stream. What I showed was only format/2 (binary predicate). Read the documentation to figure out how to use it. –  Sep 05 '21 at 01:36