Reputation: 527
Let's say I have the following 3x3 Grid of unbound variables & another list L of bound variables. I want to link both. For example.
Grid A:
[[_6308, _6314, _6308], [_6308, _6308, _6314], [_6314, _6308, _6308]]
List B:
[1 , 2 , 3]
I want to choose in order from left to right the variables and bound them to the unbound ones. in this case the 3 will be ignored cause I only have 2 unbound variables.
Result list should be:
[[1,2,1],[1,1,2],[2,1,1]]
?- fill([1,2,3],[[_6308, _6314, _6308], [_6308, _6308, _6314], [_6314, _6308, _6308]]).
[[2, 1, 2], [2, 2, 1], [1, 2, 2]]
Any idea how I can implement that? I tried this idea, but it's in complete as it only returns 1 for all elements.
fill(_,[]) .
fill(L,[H|T]):-
helper(L,H),
fill(L,T).
helper(_,[]).
helper(L,[H|T]) :-
member(H,L),
helper(L,T).
Upvotes: 3
Views: 681
Reputation: 4998
You can use term_variables/2
to find a list of variables in your term and claim it is a prefix of your term list:
prefix_of([],_).
prefix_of([X|Xs],[X|Ys]) :-
prefix_of(Xs,Ys).
grid_pool(Grid,Pool) :-
term_variables(Grid,Vs),
prefix_of(Vs,Pool).
For your example you get:
?- G = [[A, B, A], [A, A, B], [B, A, A]], grid_pool(G, [1,2,3,4]).
G = [[1, 2, 1], [1, 1, 2], [2, 1, 1]],
A = 1,
B = 2.
The order of variables in Vs
is the order of the term traversal: depth-first and left-to right.
Upvotes: 3
Reputation: 18663
How exactly you bound the variables with the values? For example, with the following rewrite of your code I'm unifying variables with the values chosen also left-to-right:
fill(Values, Variables) :-
% invert argument order to take advantage
% of first-argument indexing
fill_variables(Variables, Values).
fill_variables([], _).
fill_variables([List| Lists], Values) :-
helper(List, Values),
fill_variables(Lists, Values).
helper([], _).
helper([Variable| Variables], [Value| Values]) :-
( var(Variable) ->
% unbound variable; unify with the next value
Variable = Value,
helper(Variables, Values)
; % already bound variable
helper(Variables, [Value| Values])
).
We get:
| ?- L = [[A, B, A], [A, A, B], [B, A, A]], fill([1,2,3], L).
A = 1
B = 2
L = [[1,2,1],[1,1,2],[2,1,1]]
yes
Upvotes: 1