Search code examples
prologuniqueclpfd

Prolog Beginner: How to make unique values for each Variable in a predicate


I have a prolog predicate:

Add( [A|B] , Answer ) :-
    ...
    ~ Add everything in the list to come up with answer
    ...

I would now like to implement AddUnique that would return unique values for everything in the list except when I give it the variable twice.


Here are somethings that are logically equivalent:

?- AddUnique([A, B, C], 10). is equivalent to: ?- Add([A, B, C], 10), A != B, B != C, A != C.

And:

?- AddUnique([A, B, B], 10). is equivalent to: ?- Add([A, B, B], 10), A != B.

Also:

?- AddUnique([A, B, B], 10). is NOT equivalent to: ?- Add([A, B, B], 10), A != B, B!=B.


If ?- AddUnique([A,B,C,D], 4). is given it should return false since it cannot come with unique positive integers that add to four.

If ?- AddUnique([A,A,A,A], 4). is given it should return A=1.


Question: How can I move the A != B, B != C, A != C. logic inside the predicate without doing something like this A != A?


Solution

  • This is the solution that I came up with. It will only assign the input to be numbers less than ten but works great for that!

    addUnique( A, Answer ) :- 
        used(A,[0,1,2,3,4,5,6,7,8,9],_),
        add(A,Answer).
    
    add( [A|B] , Answer ) :-
        ~ Add everything in the list to come up with answer ~.
    
    
    % ================================
    % Ensures that all variables are unique.  
    % ================================
    
    % Base case: Assigned variables unique values
    used([], Nin, Nin).
    
    % Have already assigned a value to this variable
    used([A|B], Nin, Nout) :-
            integer(A),
            helper(B,Nin,Nout).
    
    % Have not assigned a value to this variable yet
    % Assign it and remove it from the list.  
    used( [A|B] , Nin, Nout) :-
            member(A,Nin),
            delete(Nin,A,Temp),
            helper(B,Temp,Nout).