Search code examples
prolog

Find the divisors of a number using Prolog by using recursion


I want to print the divisors of a number in Prolog and I have made the following code:

find_and_display_divisors(N) :-
    write('Divisors of '), write(N), write(':'), nl,
    find_divisors(N, 1).

find_divisors(N, D) :-
    D =< N,
    0 is N mod D,
    write(D), write(' '),
    NextD is D + 1,
    find_divisors(N, NextD).
find_divisors(_, _).

The problem that I have is that when I call my program with find_and_display_divisors(8), it only prints 1 2 true; however, it is missing the other values like 4 and 8. What am I missing?


Solution

  • When a number is not a divisor, you still need to go to next step. find_divisors(_, _) just stops the iteration at the first non-divisor.

    So you will need a new clause covering the non-divisor part.

    find_divisors(N, D) :-
        D =< N,
        M is N mod D,
        M > 0,
        NextD is D + 1,
        find_divisors(N, NextD).
    

    You might want to include this if you want the predicate to succeed.

    find_divisors(N, D) :- N < D.
    

    PS: TA_intern's answer is idiomatic way to do it. Decouple side effects from logic code as much as possible.

    Full working code:

    find_and_display_divisors(N) :-
        write('Divisors of '), write(N), write(':'), nl,
        find_divisors(N, 1).
    
    find_divisors(N, D) :-
        D =< N,
        0 is N mod D,
        write(D), write(' '),
        NextD is D + 1,
        find_divisors(N, NextD).
    
    find_divisors(N, D) :-
        D =< N,
        M is N mod D, M > 0,
        NextD is D + 1,
        find_divisors(N, NextD).
    
    find_divisors(N, D) :- N < D. % you can ignore this if you just need to print