Search code examples
if-statementrecursionprologtail-recursionsublist

Finding a sublist that meets certain criteria with a tail-recursive Prolog programm


What I want to do: I want to write a tail recursive Prolog programm that searches a list of integers for the longest ascending sequence and save the starting and end index of this sublist.

e.g.

?- longest_asc_sublist([1,2,3,2,8,4,7,8,10,11,7,-1],From,To).
From = 6,
To = 10.

What I've got so far and what my problem is: Basically I've tried to implement an algorithm by it's pseudo-code that would do just what i need, but my problem is that i cant seem to figure out how to either make this work with if statements, without 'else' following them, that have multiple actions in their statement or do it without if's

longest_asc_sublist(List,_,_) :- longest_asc_sublist(List,1,1,1,0,1,1).
longest_asc_sublist([],V,K,K,_,V,_).
longest_asc_sublist([X,Xs|Xss],_,_,K,T,V,M) :-

                            K1 is K+1, T1 is T+1,

                            Xs < X, !,           % this would be an if condition
                            T1 is 1, V1 is K,    % and this the statement

                            T1 > M, !,                       % 2.if condition
                            M1 is T1, To1 is K, From1 is V,  % statement

                            longest_asc_sublist(Xss,To1,From1,K1,T1,V1,M1).

My biggest problem is that I cant make it go beyond the "Xs < X", as soon as it evaluates to false, the program terminates and returns false.

So my 2 questions are:

How could i make this program not terminate when "Xs < X" is false?

Is there a way to implement those if's like this?:

(Xs < X ->
(T1 is 1, V1 is K)),

without it causing termination if it evaluates to false?


Solution

  • The easy answer, without going into your code, is that:

    (   condition
    ->  if condition is true
    )
    

    is equivalent to:

    (   condition
    ->  if condition is true
    ;   false
    )
    

    (as you have already noticed yourself)

    What you probably need is:

    (   condition
    ->  if condition is true
    ;   true
    )
    

    An if-else then-else if-then... looks like this:

    (   if
    ->  then
    ;   else if
    ->  then
        % and so on
    )
    

    while two ifs after each other, of course,

    (   if
    ->  then
    ;   true
    ),
    (   if
    ->  then
    ;   true
    )
    

    And now about the is: if you actually want to simply unify a variable with another, and you can't do it directly by simply using the same variable name, then you should unify then explicitly, using =:

    T1 = 1