Search code examples
prolog

Return the list of users in prolog


My goal is return the list of X users with T tags in common with a specific user and one of them is mandatory.

I have this Knowledge Base:

%node(Id, Name, ListOfTags)
node(1,ana,[nature,cat,dog,sw,csharp]).
node(11,antonio,[cat,nature,car,sport,city]).
node(22,isabel,[nature,cat,test,dog,c]).
node(23,john,[nature,dog,sw,csharp,city]).
node(24,maria,[nature,e,b,c,d]).

based on this predicate:

suggest_group(Name, NumberOfUsers, MandatoryTag, ListOfGroup)

when the question ?- suggest_group(ana, 3, cat, LGroup) is asked the result must be LGroup = [] because there is no group of 3 users with the mandatory tag cat with ana.

If i make the question suggest_group(ana, 2, cat, LGroup) the result must be LGroup = [antonio, isabel] because they have the mandatory tag cat in common with ana.

I have this:

users_x_common_tags(CurrentUser,NumberOfTags, NumberOfUsers, MandatoryTag, List_Result):-
    node(_,CurrentUser,Tags),
    findall(User,(node(_,User,_),User \== CurrentUser),Users),
    users_x_common_tags2(NumberOfTags, NumberOfUsers, MandatoryTag, Tags,Users,List_Result).

users_x_common_tags2(_,_,_,_,[],[]):-!.
users_x_common_tags2(X,N,M,Tags,[U|Users],Result):-
    node(_,U,User_Tags),
    intersection(Tags, User_Tags,Commun),
    member(M,Commun),
    length(Commun, Size),
    Size >= X, !,
    users_x_common_tags2(X,N,M,Tags,Users,Result1),
    append([U], Result1, Result).
    
users_x_common_tags2(X,N,M,Tags,[_|Users],Result):-
    !,
    users_x_common_tags2(X,N,M,Tags,Users,Result).

How can i return the list if the length its NumberOfUsers otherwise return an empty List?

Any help is welcome.


Solution

  • This isn't the prettiest code I've written, but I think it works:

    node(1,ana,[nature,cat,dog,sw,csharp]).
    node(11,antonio,[cat,nature,car,sport,city]).
    node(22,isabel,[nature,test,dog,cat]).
    node(23,john,[nature,dog,sw,csharp,city]).
    node(24,maria,[nature,e,b,c,d]).
    
    suggest_group(Name, NumberOfUsers, MandatoryTag, ListOfGroup) :-
        findall((X,Xs),(node(_,X,Xs),X \== Name,member(MandatoryTag,Xs)),Zs),
        (collapse(Zs,(ListOfGroup,_)),length(ListOfGroup,NumberOfUsers);ListOfGroup=[]).
    
    collapse([(U,Ts)],([U],Ts)).
    collapse([(U,Ts)|Rs],([U|Us],Xs)) :-
        collapse(Rs,(Us,Ws)),
        intersection(Ts,Ws,Xs).
    
    ?- suggest_group(ana, 3, cat, LGroup).
    LGroup = [].
    
    ?- suggest_group(ana, 2, cat, LGroup).
    LGroup = [antonio, isabel] .