Search code examples
prologprimes

prolog list of all divisors of a number


I want to find all the divisors of a natural number.and output a list.

now my code looks like this:

divisors(0,[]).
divisors(N,[N1|P]):- 
    N1=N,
    RES is (N mod N1),
    N1 is N-1, 
    RES==0,
    divisors(N,P).
divisors(N,[N1|P]):- 
    N1=N,
    RES is (N mod N1),
    N1 is N-1, 
    RES\=0,!, fail.

but it doesn't work. tell me, what am I doing wrong? I've seen what can be done via findall, but I want to do it differently.The idea is as follows. Subtract one from the number (whose divisors we are looking for) each time and if the original number is divided by a new number, then write it to the head of the list.

(I just realized..That I don 't remember N anywhere ..since with recursive calls, it will already be different. I'm completely confused..)


Solution

  • (I just realized..That I don 't remember N anywhere ..since with recursive calls, it will already be different. I'm completely confused..)

    That's right, there is no concept of nested scope in Prolog. Instead, we pass everything we need further down among the predicate's arguments, possibly using additional arguments.

    Minimal edit to fix your code:

    divisors(N,L):- divisors(N,N,L).
    
    divisors(N,0,[]):- !.
    divisors(N,N1,[N1|P]):-    % use N1
        %N1=N,
        RES is (N mod N1),
        N2 is N1-1, 
        RES==0,
        divisors(N,N2,P).      
    divisors(N,N1,P):-         % skip N1
        %N1=N,
        RES is (N mod N1),
        N2 is N1-1, 
        RES\=0, %!, fail
        divisors(N,N2,P).      % same P
    

    The result list L is instantiated in the top-down fashion.

    Examples:

    49 ?- divisors(12,L).
    L = [12, 6, 4, 3, 2, 1].
    
    50 ?- divisors(37,L).
    L = [37, 1].