Kindly asking for Directions and Guidance about Single Predicate and Single Rule to find 3 items in list in decreasing by 2

Hello swi-prolog,

Thank you in advance for your time and advice.

I have been tasked to write a single predicate and single rule prolog that takes in a list and find if it have 3 items in decreasing by order of 2. true if it does and false if not.

My single predicate and single rule:

ten_by_two([A, B, C | T]) :- B is C - 2, A is B - 2, ten_by_two([B, C | T]).

Tests:
ten_by_two([1, 10, 5, 3, 42, 23, 5]). %“false”

ten_by_two([5, 23, 42, 3, 5, 10, 1]). % “true, for [5, 3,1].”

During trace, I see that the predicate and rule is not performing the rule through all the elements of the list. Kindly requesting guidance and direction as to how to properly solve the problem and understand the solution.

Thank you,
hcxs

I think the first step in finding a solution is to understand what your current code does. It takes a single list argument with 3 or more items. So it will fail on shorter lists - is that what you want?

Next it takes the first three elements of the list and tests whether the difference between successive elements is 2, i.e., B is C - 2, A is B - 2. So the predicate will fail if that is not the case (there is no alternative as written). Is that what you want?

Finally, if the preceding test succeeds, it makes a recursive call with a list that’s one shorter in length. Eventually that will fail because there is no alternative specified for lists of length less than 3.

In summary, this predicate will never succeed, no matter what list you give it. It will either fail because the list argument is too short or because the first three elements fail the arithmetic comparison test.

So I would start by defining the conditions for success.

A second question is are you sure you understand the the restrictions imposed by the task? There appear to be a number of decision points dictating alternatives, e.g., given B is C-2, what do you do when it’s true and when it’s false? The normal way of separating or-cases in Prolog is with different clauses of a single predicate. Does this conflict with the:

requirement? If so, you’re forced into using the control predicates (e.g., ->/2) which I wouldn’t recommend if you’re just learning the language.

Assuming I understand your task, I think a solution is possible, but it’s not pretty and it’s not simple. So I’d suggest you start with a simpler sub-problem, e.g., find any two elements of a list, not necessarily successive, in which the first element is greater than the second by 2, using a single predicate with as many clauses as you want. Example usage:

?- pair_by_2([5,4,3,2,1],P).
P =  (5, 3) ;
P =  (3, 1) ;
P =  (4, 2) ;
P =  (3, 1) ;
false.

Hint: one solution uses 3 clauses for pair_by_2, each with a single sub-goal.

I think if you can solve this sub-problem, you’ve got a good head start on your bigger task.

Thank you, Ridgeworks!