views:

118

answers:

3

How would you code a program in Prolog to print numbers from 1 to 10 using recursion?

I've tried the following but it doesn't work, can you tell me why?

print_numbers(10) :- write(10).

print_numbers(X) :- write(X),nl,X is X + 1, print_numbers(X).
A: 

Been a seriously long time since I wrote any prolog but I'd probably do things just a little differently. Something like this, though I can't test it at the momment.

print_increasing_numbers(From, To):- From > To, !, write('ERROR: From > To').

print_increasing_numbers(To, To):- !, write(To).

print_increasing_numbers(From, To):- write(From),
                                     nl,
                                     Next is From + 1,
                                     print_increasing_numbers(Next, To).

A key difference here is the !, or cut operation, which stops backtracking. If you don't include it then you will get a solution with the first clause when X is 10,but if you ask for a second solution it will backtrack and match the second clause as well. That would result in a much larger list of numbers than you want.

torak
Mmmmmm, I tried that and it doesn't work, it prints "1ERROR: >/2: Arguments are not sufficiently instantiated Exception: (7) print_increasing_numbers(_G272+1, _G305) ? creep"
dasen
-1 for not testing your code and for not evaluating "X+1"
Kaarel
@Kaarel: Thanks. Had forgotten about that aspect of prolog's behavior. With that fix made, and remembering to rename X and Y to From and To, it ran fine.
torak
+6  A: 

Your code is very close to working. The problem is that you cannot reuse X, once it is instantiated, it cannot be changed (see here for more details). Use a new variable, like this:

print_numbers(10) :- write(10), !.
print_numbers(X) :- write(X), nl, Next is X + 1, print_numbers(Next).

Adding the cut (!) to the end will prevent the interpreter from asking if you want to see more results.

?- print_numbers(1).
1
2
3
4
5
6
7
8
9
10

Yes
?- 
Jeff Dallien
Just want to add on to this. You can use reuse a variable if its backtracked. So if you have an uninitialized value and you initialize it to get a value and it backtracks, it will go to its original form of uninitialized and it will then initialized again when it tries another answer. Kind of like if you had test(1). test(2). test(3). and you type in test(X). to the console it will give you 1,2 and 3 because of backtracking.
Matt
A: 
print_from_1_to_10 :-
        print_from_X_to_10(1).

print_from_X_to_10(X) :-
        (
                X > 10
        ->
                fail
        ;
                writeln(X),
                NewX is X + 1,
                print_from_X_to_10(NewX)
        ).
Kaarel