Eolas
Eolas

Reputation: 1

Prolog Programming List Arithmetic

Here is my code to make a countdown procedure which when I type in countdown(5,L). should return L = [5,4,3,2,1] and countdown(5,[5,4,3,2,1]) should return true.

The input countdown(5,L). returns

ERROR: is/2: Type error: []' expected, found[5,4]' ("x" must hold one character)

which shows me my program is beginning to create the list.

%countdown
countdown(1,[1]).
countdown(A,L) :-
    concat([],[A],Z),
    makeList(Z,A,List),
    L is List.

makeList(X,Y,List) :-
    N1 is Y-1,
    N1 > 0,
    concat(X,[N1],Z),
    List is Z,
    makeList(Z,N1,List).

concat([],Y,Y).
concat([H|X],Y,[H|Z]):-
    concat(X,Y,Z).

Upvotes: 0

Views: 299

Answers (2)

Nicholas Carey
Nicholas Carey

Reputation: 74197

Some comments on your code:

  • countdown/2, clause 2, line 1:

    concat([],[A],Z) is completely unnecessary. At the end of this exercise, Z is unified with [A].

  • countdown/2, clause 2, line 3:**

    As was pointed out, is/2 evaluates the right hand term as an arithmetic expression and unifies the result with the left-hand side. This should be L = List.

    Even better, just change the line above from makeList(Z,A,List) to makeList(Z,A,L).

But this is overly complicated. If one was to take your general approach, you could do it thusly:

count_down(N,L) :- % To count down to 1 from N,
  integer(N) ,     % N must first be integral
  N > 0 ,          % and positive
  range(N,1,L).    % Then you just need to generate the desired range.

range/3 could be implemented simply as this:

range( X , Y , [X]    ) :- X = Y .
range( X , Y , [X|Xs] ) :- X > Y , X1 is X-1 , range(X1,Y,Xs) .
range( X , Y , [X|Xs] ) :- X < Y , X1 is X+1 , range(X1,Y,Xs) .

Upvotes: 0

Eugene Sh.
Eugene Sh.

Reputation: 18299

Why so difficult?

countdown(1, [1]).
countdown(N, [N|T]) :-
    N1 is N-1,
    countdown(N1, T).

Upvotes: 1

Related Questions