Graver
Graver

Reputation: 11

Prolog Lists - Finding items with multiple constraints

I need to write a prolog program "dump." that can get data from a database with constraints:

Imagine this simple database a(Int,Color)

a(1,blue).
a(1,red).
a(1,green).
a(2,green).
a(3,yellow).
a(3,blue).
a(4,green).
a(4,purple).
a(4,blue).
a(4,red).

I need my program "dump." to give me all the Int elements that are related to the Color 'blue' and 'red' and is related to any other color and only output the color that is not blue and red. an example query would be

?- dump.
1 green
4 purple 
4 green
true

Here i would not care to know that 3 is related to yellow because 3 is not related to both blue and red.

Can anyone help me? :)

Upvotes: 1

Views: 119

Answers (2)

false
false

Reputation: 10102

First of all, stick to pure relations! There is no need to print things, for Prolog does the printing for you.

redblue_number(Nr) :-
   a(Nr, red),
   a(Nr, blue).

nr_related(Nr, Related) :-
   redblue_number(Nr),
   dif(Related, red),
   dif(Related, blue),
   a(Nr, Related).

?- nr_related(Nr, Related).
   Nr = 1, Related = green
;  Nr = 4, Related = green
;  Nr = 4, Related = purple
; false.

Upvotes: 1

Nicholas Carey
Nicholas Carey

Reputation: 74277

Try something this:

dump :-
  a(X,C)                     , % find an int/color pair
  related_to_red_and_blue(X) , % - such that the int is related to both red and blue, and
  not_red_or_blue(C)         , % - such that the color is not red or blue itself.
  dump(X,C)                  , % - log to the console
  fail                       . % - fail, inducing backtracking to find the next solution, 
dump.                          % and finally, succeed.

related_to_red_and_blue(X) :- a(X,red) , a(X,blue) .

not_red_or_blue(C) :- C \= red , C \= blue .

It does rather make the assumption that no color is related to the same integer more than once. It will also always succeed, even if nothing matches the constraints.

You could also do something like this, reusing the above related_to_red_and_blue/1 and not_red_or_blue/1 predicates:

dump :-
  setof( X:C , ( a(X,C) , related_to_red_and_blue(X) , not_red_or_blue(C) ) , Matches ) ,
  dump(Matches)
  .

dump( [] ) .
dump( [X:C|Ms] ) :-
  write(X) ,
  write(' ') ,
  write(C) ,
  nl ,
  dump(Ms)
  .

The above

  • uses setof/3 to find the distinct set of pairs matching the constraints.
  • recursively dumps them to the console
  • succeeds.

It will fail if nothing matches the constraints.

Upvotes: 0

Related Questions