1

Given a list L I would like to see if a pair P, appears in the list. If the element is found, then print *Found*.

For example:

L = [3,1,2,5,4,7].
P = (2,5).

Given this example, I should get *Found* as 2,5 appears on 2nd and 3rd position in list L.

Here is my approach , but I am getting a false answer.

search_pair([_|[]],_).
search_pair([X|T],(F,L)) :-
   first(Y, T),
   write('searching: '),write(F),write(' '),write(L),nl,
   write('trying: '),write(X),write(' '),write(Y),nl,
   ((F == L , L = Y) -> (write('Found'))
   search_pair(T,(F,L),R).
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Haki Terror
  • 343
  • 3
  • 15
  • Possible duplicate of [Prolog - how to check if a list includes certain elements?](http://stackoverflow.com/questions/5188084/prolog-how-to-check-if-a-list-includes-certain-elements) – Manav Dubey Apr 27 '17 at 00:21
  • 1
    i am searching for a consecutive pair , this is the thing :/ – Haki Terror Apr 27 '17 at 00:23
  • You have syntax errors in line 6, a missing closing paren and a comma. Also, 'first' is not defined, and I assume your last line should call search_pair/2 and not search_pair/3, which is also undefined – vmg Apr 27 '17 at 00:55
  • 1
    This is much easier than you're making it. You can describe a list of at least two elements as, `[X, Y | T]` where `T` is the rest of the list (may be empty `[]`). And the rest of that list excluding the first element is `[Y | T]`. – lurker Apr 27 '17 at 01:20
  • 2
    Do not mix side effects with the actual program logic. – false Apr 27 '17 at 11:07

1 Answers1

3

The actual relation is quite easy to describe. There are two cases:

  • case 1: The list starts with the given pair. In this case we're done.

  • case 2: Otherwise we need to keep searching in the tail of the list.

This can be written with if_/3 and (',')/3 like so:

pair_in((X,Y),[A,B|Cs]) :-
   if_((X=A,Y=B),
       true,                    % <- case 1
       pair_in((X,Y),[B|Cs])).  % <- case 2

Querying this with your example and a counterexample:

   ?- pair_in((2,5),[3,1,2,5,4,7]).
yes
   ?- pair_in((2,4),[3,1,2,5,4,7]).
no

If you want to output the message *Found* in the case of success, I would suggest to relocate that to a calling predicate, e.g. your predicate search_pair/2:

search_pair(L,P) :-        % <- calling predicate
   pair_in(P,L),           % <- actual relation
   format('*Found*~n').    % <- output

Now let's query this predicate with the above examples:

   ?- search_pair([3,1,2,5,4,7],(2,5)).
*Found*
yes
   ?- search_pair([3,1,2,5,4,7],(2,4)).
no

As you can see *Found* is only displayed in the case of success. That is because in case the goal pair_in(P,L) fails, Prolog doesn't move on to the next goal, since the rule cannot become true any more.

tas
  • 8,100
  • 3
  • 14
  • 22