Search code examples
prologlogic-programming

Prolog combinatorics


Is there any way to generate all possibilities like 9 letters to be divided in 3 teams, like this:

  • 1st team: 2 letters
  • 2nd team: 3 letters
  • 3rd team: 4 letters
  • ?

Example:

find([a, b, c, d, e, f, g, h, i], T1, T2, T3).
T1 = [a, b]
T2 = [c, d, e]
T3 = [f, g, h, i]

Next generation should be the next combination, until there are no more combinations.


Solution

  • Is there a way? Of course:

    -Pick 2 members of the original list, place them in T1.
    -Pick 3 members in the rest and place them in T2.
    -The rest is T3:

    teams(L, T1, T2, T3) :-
        pick2(L, T1, L1),
        pick3(L1, T2, T3).
    
    pick2(L, [M1, M2], Rest) :-
        member(M1, L),   
        delete(L, M1, L1),
        member(M2, L1),
        delete(L1, M2, Rest).
    
    pick3(L, [M1, M2, M3], Rest) :-
        pick2(L, [M1, M2], L1),
        member(M3, L1),
        delete(L1, M3, Rest).
    

    The query

    :- teams([a,b,c,d,e,f,g,h,i], T1, T2, T3).
    

    is producing the requested output. Please note, the code above is assuming the input is in correct format (i.e. the list has correct number of elements).

    Update: You can use the select/3 predicate in SWI prolog instead of member/delete combinations:

    teams(L, T1, T2, T3) :-
        pick2(L, T1, L1),
        pick3(L1, T2, T3).
    
    pick2(L, [M1, M2], Rest) :-
        select(M1, L, L1),
        select(M2, L1, Rest).
    
    pick3(L, [M1, M2, M3], Rest) :-
        pick2(L, [M1, M2], L1),
        select(M3, L1, Rest).