Search code examples
prologprocessing-efficiency

Prolog: efficiency


Is there a way in prolog to make the following shorter:

rule(prop, [1/2,2/2]).
rule(prop, [1/3,2/3,3/3]).
rule(prop, [1/4,2/4,3/4,4/4]).
rule(prop, [1/5,2/5,3/5,4/5,5/5]).
rule(prop, [1/6,2/6,3/6,4/6,5/6,6/6]).
rule(prop, [1/7,2/7,3/7,4/7,5/7,6/7,7/7]).

Solution

  • The following code isn't necessarily "shorter" for the case of 6 different rules, but it is more scalable, which is probably what you really mean.

    You can break this down as follows. First, a rule that generates one list:

    list_props(N, N, [N/N]).
    list_props(X, N, [X/N|T]) :-
        X >= 1,
        X < N,
        X1 is X + 1,
        list_props(X1, N, T).
    

    When you call this, it generates one list of proportions from the first argument to the last with the last argument being the denominator. For example:

    | ?- list_props(1, 4, L).
    
    L = [1/4,2/4,3/4,4/4] ? a
    
    | ?-
    

    Note that you could enforce that N be an integer >= 1 using integer(N) and conditions, but I was being brief and didn't do that in the above.

    You can use this in your top level predicate:

    rule(prop, L) :-
        between(2, 7, X),
        list_props(1, X, L).
    

    Which yields:

    | ?- rule(prop, L).
    
    L = [1/2,2/2] ? ;
    
    L = [1/3,2/3,3/3] ? ;
    
    L = [1/4,2/4,3/4,4/4] ? ;
    
    L = [1/5,2/5,3/5,4/5,5/5] ? ;
    
    L = [1/6,2/6,3/6,4/6,5/6,6/6] ? ;
    
    L = [1/7,2/7,3/7,4/7,5/7,6/7,7/7] ? ;
    
    (2 ms) no
    | ?-