I'm trying to solve a new program with Prolog, and I'm stuck, and don't know how to continue... I must do a predicate that has 3 arguments, the first is a list of elements, the second one is a list of tuples, and the third one must be a list returned that contains the second element of the tuples, if the first element of the tuple match with an element of the first argument list. It must delete copies also!!
For example,
check([a,c],[(a,aa),(bb,bbb),(a,aa),(c,def)],X).
X = [aa, def] .
As you can see, a and c match on the list of tuples, so return the second element of the tuples.
So it works, BUT if there is more than one tuple that contains a first element that match on the first list, it only will take once, for example:
check([a,b],[(a,c),(a,d),(b,c),(b,e),(c,f)],X).
X = [c] .
It finds a the first time and took c, and b the first time and took c again, but not iterate to find more a or b, the right result should be X=[c,d,e].
So please, I ask you help on how to solve this situation or any clue to solve it...
Here is my code:
check([],_,[]).
check(L,DIC,Xord) :- inter(L,DIC,X), list_to_set(X,Xord).
inter([],_,[]).
inter(L1, DIC, L3) :-
L1 = [H|T],
DIC = [(DIC1,DIC2)|_],
H == DIC1,
L3 = [DIC2|L3T],
inter(T, DIC, L3T).
inter(L1,[_|DIC],L3) :- inter(L1,DIC,L3).
inter([_|T], DIC, L3) :- inter(T, DIC, L3).
Thanks in advance for your time.
For an easier understandable version I propose the following:
:- use_module(library(lists)).
keys_dict_uniquevalues(Ks,D,UVs) :-
keys_dict_values(Ks,D,Vs), % Vs ... values with duplicates
list_set(Vs,UVs). % UVs ... Vs deduplicated
keys_dict_values([],_D,[]). % No keys no values
keys_dict_values([Key|Keys],D,Vs) :-
key_dict_values(Key,D,Matches), % all Matches for Key
keys_dict_values(Keys,D,OtherVs), % Matches for other Keys
append(Matches,OtherVs,Vs). % all found values in Vs
key_dict_values(_K,[],[]). % no mathes if dictionary empty
key_dict_values(K,[(K,V)|Pairs],[V|Vs]) :- % Value is in list if key matches
key_dict_values(K,Pairs,Vs).
key_dict_values(K,[(X,_V)|Pairs],Vs) :- % Value is not in list
dif(K,X), % if key doesn't match
key_dict_values(K,Pairs,Vs).
list_set([],[]). % empty list contains no duplicates
list_set([X|Xs],[X|Ys]) :- % head of the first list
subtract(Xs,[X],Zs), % doesn't occur in Zs
list_set(Zs,Ys).
If you want so write a program without the use of library(lists) you have to replace the goal append/3 in keys_dict_values/3 and the goal subtract/3 in list_set/2. In the below example by lists_appended/3 and list_x_removed/3:
keys_dict_uniquevalues(Ks,D,UVs) :-
keys_dict_values(Ks,D,Vs),
list_set(Vs,UVs).
keys_dict_values([],_D,[]).
keys_dict_values([Key|Keys],D,Vs) :-
key_dict_values(Key,D,Matches),
keys_dict_values(Keys,D,OtherVs),
lists_appended(Matches,OtherVs,Vs).
key_dict_values(_K,[],[]).
key_dict_values(K,[(K,V)|Pairs],[V|Vs]) :-
key_dict_values(K,Pairs,Vs).
key_dict_values(K,[(X,_V)|Pairs],Vs) :-
dif(K,X),
key_dict_values(K,Pairs,Vs).
lists_appended([],L,L).
lists_appended([X|Xs],Ys,[X|Zs]) :-
lists_appended(Xs,Ys,Zs).
list_set([],[]).
list_set([X|Xs],[X|Ys]) :-
list_x_removed(Xs,X,Zs),
list_set(Zs,Ys).
list_x_removed([],_X,[]).
list_x_removed([X|Xs],X,Ys) :-
list_x_removed(Xs,X,Ys).
list_x_removed([X|Xs],Z,[X|Ys]) :-
dif(X,Z),
list_x_removed(Xs,Z,Ys).
The queries given in the above exmaple work for both versions:
?- keys_dict_uniquevalues([a,c],[(a,aa),(bb,bbb),(a,aa),(c,def)],X).
X = [aa,def] ? ;
no
?- keys_dict_uniquevalues([a,b],[(a,c),(a,d),(b,c),(b,e),(c,f)],L).
L = [c,d,e] ? ;
no
The counterexample provided by @false fails for both versions as expected:
?- keys_dict_uniquevalues([a,b],[(a,c),(a,d),(b,c),(b,e),(c,f)],[c,c]).
no
The unusual usage as suggested by @false:
?- keys_dict_uniquevalues([a,b],[KV1,KV2],[e]).
KV1 = KV2 = (a,e) ? ;
KV1 = (a,e),
KV2 = (b,e) ? ;
KV1 = (a,e),
KV2 = (_A,_B),
dif(b,_A),
dif(a,_A) ? ;
KV1 = (b,e),
KV2 = (a,e) ? ;
KV1 = (_A,_B),
KV2 = (a,e),
dif(b,_A),
dif(a,_A) ? ;
KV1 = KV2 = (b,e) ? ;
KV1 = (b,e),
KV2 = (_A,_B),
dif(b,_A),
dif(a,_A) ? ;
KV1 = (_A,_B),
KV2 = (b,e),
dif(b,_A),
dif(a,_A) ? ;
no