I am currently trying to solve this problem.
The generator generate/2 is to produce all valid combinations for a window.
generate(Gs,Cs) :-
colorset(Gs,Cs),
valid(Gs,Cs).
?- genere([b,c,d,i,j],C).
C = [red , yellow, red , yellow, blue ] ;
C = [red , yellow, red , blue , yellow] ;
C = [red , yellow, blue , yellow, red ] ;
C = [red , yellow, blue , blue , red ] ;
C = [red , yellow, blue , blue , yellow] ;
C = [red , blue , red , yellow, blue ] ;
C = [red , blue , red , blue , yellow] ;
C = [red , blue , yellow, yellow, red ] ;
C = [red , blue , yellow, yellow, blue ] ;
C = [red , blue , yellow, blue , red ] ;
C = [yellow, red , yellow, red , blue ] ;
C = [yellow, red , yellow, blue , red ] ;
C = [yellow, red , blue , red , yellow] ;
C = [yellow, red , blue , blue , red ] ;
C = [yellow, red , blue , blue , yellow] ;
C = [yellow, blue , red , red , yellow] ;
C = [yellow, blue , red , red , blue ] ;
C = [yellow, blue , red , blue , yellow] ;
C = [yellow, blue , yellow, red , blue ] ;
C = [yellow, blue , yellow, blue , red ] ;
C = [blue , red , yellow, red , blue ] ;
C = [blue , red , yellow, yellow, red ] ;
C = [blue , red , yellow, yellow, blue ] ;
C = [blue , red , blue , red , yellow] ;
C = [blue , red , blue , yellow, red ] ;
C = [blue , yellow, red , red , yellow] ;
C = [blue , yellow, red , red , blue ] ;
C = [blue , yellow, red , yellow, blue ] ;
C = [blue , yellow, blue , red , yellow] ;
C = [blue , yellow, blue , yellow, red ] ;
false.
I need to the predicate valid/2.
Given the predicate colorset which I have defined as following.
colorset([],[]).
colorset([_|Nodes], [C|Color]):- color(C), colorset(Nodes, Colors).
Right now, I am trying to figure out if there's a way to generate the colorset predicate first and then check if the adjacent nodes have the same colour but I am not sure if that's possible in Prolog?
What is another alternative?
Related
the map I am using
(sorry for my bad English) I got Prolog code from a teacher but I am new to the language so I couldn't understand what conflict//no conflict//find coloring really does and why he is using nodes and lists, I searched for an explanation but I couldn't find similar code.
This is the code >>>
adjacent( 1, 2 ).
adjacent( 1, 3 ).
adjacent( 1, 4 ).
adjacent( 1, 5 ).
adjacent( 2, 3 ).
adjacent( 2, 4 ).
adjacent( 3, 4 ).
adjacent( 4, 5 ).
color( red ).
color( yellow ).
color( pink ).
color( purple ).
conflict( color( Node1, Color ), color( Node2, Color )) :-
adjacent( Node1, Node2 ).
noconflict( _, [] ).
noconflict( Coloring1, [Coloring2 | Colorings] ) :-
not( conflict( Coloring1, Coloring2 )),
noconflict( Coloring1, Colorings ).
findcoloring( [], [] ).
findcoloring( [Node | Nodes], [Coloring | Colorings] ) :-
findcoloring( Nodes, Colorings ),
Coloring = color( Node, Color ),
color( Color ),
noconflict( Coloring, Colorings ).
If you are new to the language it may be impossible to explain all of that code in a short and useful answer.
why he is using nodes and lists
The map can be seen as a graph of connections and "nodes" and "edges" are common terms for these graphs. Nodes meaning areas of the map, and them being adjacent in the picture makes for edge connections like this:
Lists are a convenient way to hold multiple things in Prolog.
The setup for the problem is these lines of facts which say e.g. that node 1 and 3 are adjacent in the map, so are 1 and 4, and that red is a color, so is yellow:
adjacent( 1, 3 ).
adjacent( 1, 4 ).
adjacent( 1, 5 ).
adjacent( 2, 3 ).
adjacent( 2, 4 ).
adjacent( 3, 4 ).
adjacent( 4, 5 ).
color( red ).
color( yellow ).
color( pink ).
color( purple ).
and this rule which says that two connected map areas cannot be the same color. It shows us that the Prolog term color(N, C) is the way the code has been written to connect map areas (nodes) with their assigned colors. It uses the same variable Color with both Node1 and Node2, there is no need for if (Color1 == Color2) like other languages might use. If two nodes are adjacent and have been given the same color, that's a conflict:
conflict( color( Node1, Color ), color( Node2, Color )) :-
adjacent( Node1, Node2 ).
Building up to the solution is the following code which checks a list of color(N, C) assignments looking for any conflicts. It checks the first one against the second one, then recursively checks the first one against all the remaining ones. If there are no conflicts found, noconflicts is true:
noconflict( _, [] ).
noconflict( Coloring1, [Coloring2 | Colorings] ) :-
not( conflict( Coloring1, Coloring2 )),
noconflict( Coloring1, Colorings ).
The following code colors the nodes, it takes a list of nodes as the first parameter findcoloring([1,2,3,4,5], Answer) and goes to the end of the list, then comes back up and assigns colors from the end [5] gets a color which is checked for no conflicts, then [4,5] both get colorings and are checked for conflicts, then [3,4,5] get colorings, etc. This is also recursive:
findcoloring( [], [] ).
findcoloring( [Node | Nodes], [Coloring | Colorings] ) :-
findcoloring( Nodes, Colorings ),
Coloring = color( Node, Color ),
color( Color ),
noconflict( Coloring, Colorings ).
The nature of how Prolog works, if there is a conflict then the noconflict() test fails, and Prolog will backtrack and undo the assigned color and try a different one as it searches for a solution. This is why there's no loop, no variable assignment, no if/else, just a declaration that the map is colored when each node has a color and there are no conflicts between any of them.
I would like to make the following piece of code work without using maplist.
only_two([Person|Choice]) :- subset([red, red], Choice), not(subset([red, red, red], Choice).
only_two([[Person|Choice]|Others]) :- only_two([Person|Choice]), only_two(Others).
Then I have
?-only_two([John, red, blue, blue, green, red]). -> True
?-only_two([[John, red, blue, blue, green, red],
[Alice, green, red, red, blue, green],
[Fred, red, red, blue, yellow, green]]). -> False
What do I do wrong?
I have a definition of conc:
conc([], L2, L2).
conc([X1|R1], L2, [X1|RN]) :-
conc(R1, L2, RN).
I don't understand why conc([X | green], Y, [red, green, blue]). returns false rather than
X = [red],
Y = [blue]
What is the process of inference here?
Disclaimer: I don't know Prolog. The rest of this answer is an edumacated guess.
Your proposed solution of X = [red] doesn't make sense because that would make X a one-element list. Let's assume
X = red
instead.
That would give us
conc([red | green], [blue], [red, green, blue]).
With the second equation of conc that turns into
conc(R1, L2, RN).
% with:
% X1 = red
% R1 = green
% L2 = [blue]
% [X1|RN] = [red, green, blue]
% i.e. X1 = red
% RN = [green, blue]
I.e.
conc(green, [blue], [green, blue]).
And now we're stuck because none of your conc rules applies to green.
The problem is [X | green] because green is not the tail of a list.
Did you mean [X, green] instead?
In Prolog list notation, the | separates the elements enumerated at its left from a list of the remaining elements at its right. The issue is in your query. Instead of [X | green] you need to write either [X | [green]] or [X,green]. With one of these fixes, you get correct answer. E.g.
?- conc([X | [green]], Y, [red, green, blue]).
X = red,
Y = [blue].
I am trying to instantiate multiple lists in Prolog of elements with only two states, the states being red and blue. Initially, I instantiate a list of elements that are only blue by creating a list of size n:
generate_list(0, []) :- !.
generate_list(N, [H | T]) :-
N2 is N-1,
H = blue,
generate_list(N2, T).
I have also defined a predicate to change the state of colors
flip(blue, red).
flip(red, blue).
I would like to use this predicate to change the color during the instantiation of a new list, however I am stuck on how to approach this problem. The default permutation and combination predicate requires you use separate predefined elements to instantiate the new list, however I have a list of elements already generated.
It's not clear from your question what you mean by "changing" the color "during the instantiation". It would be great if you could update it with a concrete example of what you want.
However, here is something that may or may not go into the direction of what you want:
color(red).
color(blue).
colorlist([]).
colorlist([C|Cs]) :-
color(C),
colorlist(Cs).
The definition of colorlist/2 says that its argument is a list, with elements satisfying color/1. Either color is fine, so any list of any permutation of elements from red and blue is a solution. We can use this already to check color lists:
?- colorlist([red, blue, blue]).
true.
And also to try to enumerate them, although the enumeration is not fair, i.e., some things that are solutions (in this case, any list containing blue) will never be generated:
?- colorlist(Cs).
Cs = [] ;
Cs = [red] ;
Cs = [red, red] ;
Cs = [red, red, red] ;
Cs = [red, red, red, red] ;
Cs = [red, red, red, red, red] . % etc.
To solve the fairness problem, we can enumerate by length: First all the length-0 lists, then all the length-1 lists, all the length-2 ones, etc. If we expose the length as a parameter, we get something that at least has the same interface as the predicate you are trying to write:
length_colorlist(N, Cs) :-
length(Cs, N),
colorlist(Cs).
This can enumerate solutions fairly and generally:
?- length_colorlist(N, Cs).
N = 0,
Cs = [] ;
N = 1,
Cs = [red] ;
N = 1,
Cs = [blue] ;
N = 2,
Cs = [red, red] ;
N = 2,
Cs = [red, blue] ;
N = 2,
Cs = [blue, red] .
And also answer more specific queries restricted by length:
?- length_colorlist(8, Cs).
Cs = [red, red, red, red, red, red, red, red] ;
Cs = [red, red, red, red, red, red, red, blue] ;
Cs = [red, red, red, red, red, red, blue, red] ;
Cs = [red, red, red, red, red, red, blue, blue] ;
Cs = [red, red, red, red, red, blue, red, red] ;
Cs = [red, red, red, red, red, blue, red, blue] ;
Cs = [red, red, red, red, red, blue, blue, red] ;
Cs = [red, red, red, red, red, blue, blue, blue] ;
Cs = [red, red, red, red, blue, red, red, red] ;
Cs = [red, red, red, red, blue, red, red, blue] .
Note: No cuts needed, and the final definition is built up as a simple composition of more generic, individually useful parts. When stuck on a problem, especially in Prolog, always try to solve individual subparts first. In this case, "how do I define lists (of any length) containing colors?" and "how do I generate lists of specific lengths?" are two distinct subproblems that are best solved separately.
EDIT 2:
I solved it using list in list. Thanks for help.
I try to make Mastermind in Prolog. I have a function
guess(Colors, Size, Possibilities, Answer, Black, White)
which takes count of used colors, size of game field, list of colors and user evaluation of answer. It may looks like:
guess(4, 6, P, [red, red, blue, green, green, yellow], 2, 3)
which means there are 4 colors, 6 places for pegs and the guess
[red, red, blue, green, green, yellow] gets 2 black pegs and 3 white.
When I call this these functions directly like
guess(4, 6, O, [red, red, blue, green, green, yellow], 2, 3),
guess(4, 6, O, [red, yellow, green, blue, red, blue], 0, 4),
guess(4, 6, O, [green, blue, yellow, red, green, yellow], 4, 2),
guess(4, 6, O, [yellow, blue, red, yellow, green, yellow], 5, 0).
it gives me correct answer O = [green, blue, red, yellow, green, yellow]
Now I try to make it more interactive, so I created functions
play:-
write('Size: '), read(Size), nl,
write('Colors: '), read(Colors), nl,
createFirstGuess(Size, Colors, [], A), //initial guess
run(Colors, Size, _, A).
run(Colors, Size, P, A) :-
tryGuess(Colors, Size, J, A), //Possibilities in J
copy(J, X), //First possible result J -> X
J = P, //Unification of all results
run(Colors, Size, J, X). //loop
tryGuess(_, _, _, []) :- !.
tryGuess(Colors, Size, P, A) :-
write('Evaluation of: '), write(A), nl,
write('Black pegs: '), read(B), nl,
write('White pegs: '), read(W), nl,
guess(Colors, Size, P, A, B, W).
copy([],[]) :- !. //Copy list T1 to T2
copy([H|T1],[H|T2]) :- !, copy(T1,T2).
createFirstGuess(0, _, L, L) :- !. //Initial guess (just field of the same colors)
createFirstGuess(N, Colors, R, L) :-
N > 0, N1 is N - 1, color(Colors, H), createFirstGuess(N1, Colors, [H|R], L).
I run 'play', set size and count of colors a start play.
Evaluation of: [red, red, red, red, red, red] //Initial guess
Black pegs: 1.
White pegs: 0.
Evaluation of: [red, green, green, green, green, green] //OK
Black pegs: 1.
White pegs: 2.
Evaluation of: [red, green, green, green, green, blue] //Bad, it goes through the list one-by-one
Black pegs: 1.
White pegs: 2.
Evaluation of: [red, green, green, green, green, yellow] //Bad
Black pegs: 2.
White pegs: 2.
Evaluation of: [red, green, green, green, blue, green] //Bad
Black pegs: 0.
White pegs: 4.
It seems the first two answers are good (one is initial, second is computed), but the next one just goes through all possibilities one-by-one. I think there is a problem with backtracking, so there should be some cuts (!), but I am unable to find where to put them.
Thanks for any help.
EDIT:
Thank you for help.
I would like to get output like this:
Evaluation of: [red, red, red, red, red, red] //Initial guess
Black pegs: 1.
White pegs: 0.
Evaluation of: [red, green, green, green, green, green]
Black pegs: 1.
White pegs: 2.
Evaluation of: [green, red, blue, yellow, green, blue]
Black pegs: 3.
White pegs: 2.
Evaluation of: [green, blue, yellow, yellow, green, red]
Black pegs: 4.
White pegs: 2.
Evaluation of: [green, blue, red, yellow, green, yellow]
Black pegs: 6.
White pegs: 0.
End of Game
But, in my case prolog goes through the list of all possibilities one-by-one but when I use guess (as shown above) it works great. There must be a problem with unification and backtracking. At first I use initial list and get correct possible results. Then I take first of results and let player to evaluate it. This first result with player evaluation I use for next guess, but there is a problem. As I see, because of backtracking is this result (answer) reunified, so player must go through the list one-by-one, no matter the evaluation.
I think, it should work, if the answer, evaluated by player, won't be reunified, but I cannot find a way to do so.
OK, I finally solved it using lists in lists for saving Answers and evaluations. Then I just expand those lists and use it for building more precise solution.