Reema Q Khan
Reema Q Khan

Reputation: 878

Print Answer using Facts

I am trying to print the values present in Facts. For example when I have the following Facts:

terrain(2,(2,4,3,1)).
terrain(2,(3,1,2,4)).
terrain(1,(4,3,1,2)).
terrain(3,(1,2,4,3)).

Input:

v([1,2,3],R).

It should give me:

R = [(4,3,1,2), (2,4,3,1), (3,1,2,4), (1,2,4,3)]

But the code isn't printing the second value of 2 i.e. (3,1,2,4) present in Facts. I am getting:

R = [(4,3,1,2), (2,4,3,1), (1,2,4,3)]

How do I get all possible values for a certain value present in a Fact.

My code:

%Facts
terrain(2,(2,4,3,1)).
terrain(2,(3,1,2,4)).
terrain(1,(4,3,1,2)).
terrain(3,(1,2,4,3)).


v([],[]).
v([H|T],[Q|R]):-
    terrain(H,Q),
    v(T,R),!.

Upvotes: 1

Views: 63

Answers (1)

false
false

Reputation: 10102

First of all, let's look at your definition. Why did you insert a cut here? Let's see what happens without it:

?- v([1,2,3],R).
   R = [(4,3,1,2),(2,4,3,1),(1,2,4,3)]
;  R = [(4,3,1,2),(3,1,2,4),(1,2,4,3)].

So with this cut you removed the second solution. Now you may not like it, but let's keep in mind your definition of v/2. To make it easier to read, I will use a generalization of your definition.

:- op(950, fy, *).
* _G_0. % to remove a goal

v([],[]).
v([H|T],[Q|R]):-
    * terrain(H,Q),
    v(T,R).

So what remains is a relation that is true when both arguments are lists of the same length. And thus also with terrain/2 added this will hold. There is no way to make the second argument a list that is longer. If you really want to change this, you have to modify already that generalized part.

v2([], []).
v2([H|Hs], Vs0) :-
   setof(V, terrain(H, V), Vs),
   append(Vs, Vs1,Vs0),
   v2(Hs, Vs1).

?- v2([1,2,3],R).
   R = [(4,3,1,2),(2,4,3,1),(3,1,2,4),(1,2,4,3)].

Alternatively, and preferably, use a DCG:

seq([]) -->
   [].
seq([E|Es]) -->
   [E],
   seq(Es).

v([]) -->
   [].
v([H|Hs]) -->
   {setof(V, terrain(H, V), Vs)},
   seq(Vs),
   v(Hs).

?- phrase(v([1,2,3]), Vs).
   Vs = [(4,3,1,2),(2,4,3,1),(3,1,2,4),(1,2,4,3)].
?- length(Hs, 2), phrase(v(Hs), Vs).
   Hs = [1,1], Vs = [(4,3,1,2),(4,3,1,2)]
;  Hs = [1,2], Vs = [(4,3,1,2),(2,4,3,1),(3,1,2,4)]
;  Hs = [1,3], Vs = [(4,3,1,2),(1,2,4,3)]
;  Hs = [2,1], Vs = [(2,4,3,1),(3,1,2,4),(4,3,1,2)]
;  Hs = [2,2], Vs = [(2,4,3,1),(3,1,2,4),(2,4,3,1),(3,1,2,4)]
;  Hs = [2,3], Vs = [(2,4,3,1),(3,1,2,4),(1,2,4,3)]
;  Hs = [3,1], Vs = [(1,2,4,3),(4,3,1,2)]
;  Hs = [3,2], Vs = [(1,2,4,3),(2,4,3,1),(3,1,2,4)]
;  Hs = [3,3], Vs = [(1,2,4,3),(1,2,4,3)].
?- Hs = [A,B], dif(A,B), phrase(v(Hs), Vs).
   Hs = [1,2], A = 1, B = 2, Vs = [(4,3,1,2),(2,4,3,1),(3,1,2,4)]
;  Hs = [1,3], A = 1, B = 3, Vs = [(4,3,1,2),(1,2,4,3)]
;  Hs = [2,1], A = 2, B = 1, Vs = [(2,4,3,1),(3,1,2,4),(4,3,1,2)]
;  Hs = [2,3], A = 2, B = 3, Vs = [(2,4,3,1),(3,1,2,4),(1,2,4,3)]
;  Hs = [3,1], A = 3, B = 1, Vs = [(1,2,4,3),(4,3,1,2)]
;  Hs = [3,2], A = 3, B = 2, Vs = [(1,2,4,3),(2,4,3,1),(3,1,2,4)].

And, btw, in Prolog it is often preferred to write v(4,3,1,2)) instead of (4,3,1,2). Just say write_canonical((4,3,1,2)). to see why.

Upvotes: 2

Related Questions