To recalculate a number using Prolog

Trivial question, but I want the program to return a list of numbers less than or equal to a given number. Eg CountD(4,L)

. must give [4,3,2,1]

. This is what I have so far:

CountD(1,[]).
CountD(Num,List):- [Num|List], CountD(M,List), Num is M+1.

      

+3


source to share


3 answers


This is also the solution:

countd(N, [N|List0]) :-
    succ(N0, N),
    countd(N0, List0).
countd(0, []).

      



Here's the important line succ(N0, N)

. This will only succeed if N> 0 and will fail if the second argument is 0 (it will also throw an error if N is not a non-negative integer).

If succ(N0, N)

not, the second sentence will be evaluated. It will only succeed when its arguments are 0 and the list is empty.

+4


source


@ Boris's answer is perfect. I would just like to explain why your original program and other answer don't end.

At first glance, it seems that this works, because we get the answer:

?- countD(4,L).
L = [4, 3, 2, 1]

      

But note that Prolog only showed us the first answer, there is more, waiting ...

?- countD(4,L).
L = [4, 3, 2, 1] ;
**LOOPS**

      

The best way to understand termination in Prolog is to focus on the relevant parts of your program. And the good thing about Prolog is that while its actual control flow is quite complex, it is often enough to look at a very small part of your program to determine certain properties. Therefore, there is no need to "understand everything at once."



Instead of looking at everything, I'll take the following failure-slice :

countD (0, []): - false .
countD (Num, List): -
   List = [Num | L],
   countD (M, L), false ,
    Num is M + 1 .

In the first line, by inserting , the fact is effectively deleted. Therefore, no matter what it describes or does not affect the termination of this predicate. In general, refusal to complete any refusal-refusal implies abandonment of the original program. false

0

1

Of course, we have to find the right cut. This is a bit of an experience. But once it is found, its completion properties are easy to check.

To fix this problem, we can tell right away that adding an extra clause will not improve completion (as long as the program is clean, monotonous). We need to change something in the visible part. Boris did this by adding some check for Num

before the actual recursion.

+4


source


countD(0,[]).
countD(Num,List) :- List = [Num|L], countD(M,L), Num is M+1.

      

UPDATED:

Fixes problems found by @false and @boris in comments:

countD(Num,[Num|L]) :- Num > 0, M is Num-1, countD(M,L).
countD(0,[]).

      

0


source







All Articles