Search code examples
recursionprologdivision

Prolog - division


I am brand new to Prolog. Literally this week. I am looking to write a recursive Prolog predicate that accepts two numbers X, Y as input. It should output to screen a list of all numbers less than or equal to X that are evenly divisible by Y.

I have been looking into this over the last few days and am thouroghly confused. I have started by trying to divide Y into 1, displaying this on screen and then repeating the process. Would anyone have tips on gettingthis working. Once I get that, I will then be trying to ensure these are less than or equal to X.

So far I have the below, which may be completely wrong. Any help is appreciated. Apologies if the formatting comes off badly.

divide(X, Y) :-
    S is 1,
    Z is Y / S,
    S is S + 1,
    write(Z),
    divide(X, Y).

Solution

  • The numbers less than 20 which divide by 3 start 3, 6, 9, ... i.e. start with the divisor 3 and count up adding 3 each time until you get past the cutoff.

    e.g.

    countup(X, Y, Counter) :-  % if the counter is below the limit,
        Counter =< X,          
        writeln(Counter),      % print it.
        
        Next is Counter + Y,   % count up by +Y, e.g. +3
    
        countup(X, Y, Next).   % loop.
    
    
    countup(X, _, Counter) :-  % if the counter is past the limit,
        Counter > X.           % stop.
    
    
    divide(X, Y) :-            % start counting from Y, e.g. 3
        countup(X, Y, Y).
    

    In your code, this line:

    S is S + 1
    

    is you saying "keep going if 2 is 3" and Prolog will say "it's not, case closed, stop here" and end your program. When you do S+1 you need to use a new variable for the result. Only the Prolog system can change variables, you can't (simplification).


    This is the shape of an infinite loop:

    divide(X, Y) :-
        ____,
        ____,
        divide(X, Y).
    

    X and Y never change so it's the same call each time; if it got past that S=S+1 then it would go round and round forever.


    This shape:

    divide(X, Y) :-
        S is 1,
        ____,
        divide(X, Y).
    

    If it worked how you are trying, it would reset S back to 1 each time.

    Since you need some case to handle looping and some case to handle stopping, and some test for passing the limit and something to pass S on through the loops, and I wanted words as variable names, quickly your short code turns into my much longer code even though it doesn't do much more.


    (I didn't start from X and divide down because that would mean X had to be a multiple of Y. I thought you should be able to ask for the numbers less than 10 which are divisible by 9 and get 9 without having to deal with 10/9=1.11...)