How to get value from a matrix in Prolog? - prolog

I'm a beginner in Prolog, so I'm still confused on how to form a recursive function in Prolog.
Let say I have a matrix:
S:
[ 5 6
3 4 ]
Represented in prolog as: S = [ [5,6], [3,4]].
I'm trying to write a recursive function to get a cell value such that cell_values (Cells, Matrix, Values) would return a list of the values from a list of the cell.
Example: cell_values ([[0,0], [0,1]], S, Values) --> Values = [5, 6]. Where S is the matrix above.
I'm thinking of using nth0 to get the value. This is my work so far.
:- use_module(library(clpfd)).
cell_values([], [], []).
cell_values([X|T], S, Values) :-
nth0(X, S, Row),
nth0(T, Row, Values).
Not sure how to fix this. Can you point me in the right direction?

There are some problems here with the predicate:
you use S and T as row number and column number, but S is the head of the list, and T the tail here. Since the list of indices is a list of lists, that means S will be a list, and T a list of lists;
you do not use recursion to generate a list of values, so if we fix the above, then it will still - at most - yield a specific value; and
the base predicate is too restrictive, since it assumes that the matrix (the second parameter), should be empty. This does not makes sense, since normally the matrix will be passed without any changes. Regardless of the matrix, if the list of indices is empty, then so is the list of values.
explicit recursion
So if we rewrite the predicate, there are two rules:
the base case: in case the list of indices is empty, then regardless of the matrix, the list of values is empty as well:
cell_values([], _, []).
in the recursive cass, we match the first list with [[R, C] | T], so R is the row number, and C the column number, T is the list of remaining lists to process, so we perform the nth0/3 as demonstrated in the question, but with R and C, and the cell value V is prepended to the result list [V|VT], the VT is then used in the recursive call to obtain more elements:
cell_values([[R, C]| T], M, [V|VT]) :-
nth0(R, M, Row),
nth0(C, Row, V),
cell_values(T, M, VT).
Or putting these together:
cell_values([], _, []).
cell_values([[R, C]| T], M, [V|VT]) :-
nth0(R, M, Row),
nth0(C, Row, V),
cell_values(T, M, VT).
maplist/3
Processing lists is a rather common thing to do, so we might be interested in using maplist/3, and write a predicate that only processes a single sublist, like:
cell_value(M, [R, C], V) :-
nth0(R, M, Row),
nth0(C, Row, V).
Then we can define the predicate cell_values like:
cell_values(Ixs, M, Vs) :-
maplist(cell_value(M), Ixs, Vs).

Related

prolog: move element between lists

I just start learning Prolog and find it's hard to handle list related problem.
If I have a list. Inside this list, I have three inner lists.
[[a,b,c], [d,e,f],[h,g]]
I need to write a predicate called "move(L, X, From, To, R)" where X is the character I want to move (this character has to be the last element in the inner list), From is the index of list I want to move from, To is the index of list I want to move to. e.g.
move([[a,b,c], [d,e,f],[h,g]], f, 2, 3, R).
returns
R = [[a,b,c], [d,e],[h,g,f]]
One more example:
move([[a,b,c], [d,e,f],[h,g]], f, 2, 1, R).
returns
R = [[a,b,c,f], [d,e],[h,g]]
I wrote a helper predicates to determine if a character is the last element in the list:
last([A], C):- A == C.
last([_|T], C):- last_one(T, C).
I spent a few hours thinking about it, but no working solutions. Any help please?
I think you must prove the following:
move(L, X, From, To, R) is the predicate you want run, so the #1 argument is a list of list (in the sample: L = [[a,b,c], [d,e,f],[h,g]] ); the #3 and #4 arguments are members of L, so you can use the predicate nth1(N, L, E), where N is the order of the element, L is the list and E the Element; each element is another list, and now you must delete the X from the list From and add it to the list To.
For it, first you can use the predicate 'select/3'; for the second, you can use 'append/3'.
I tried the folowwing rules, but it give me a different order of the main list:
move(L, X, F, T, R) :-
nth1(F, L, Lf),
nth1(T, L, Lt),
select(X, Lf, Rf),
append(Lt, [X], Rt),
select(Lf, L, Ra),
select(Lt, Ra, Rb),
append(Rb, [Rf], Rc),
append(Rc, [Rt], R).
with this code, you obtain the following:
move([[a,b,c], [d,e,f],[h,g]], f, 2, 3, R).
R = [[a,b,c], [d,e],[h,g,f]]
but:
move([[a,b,c], [d,e,f],[h,g]], f, 2, 1, R).
R = [[h,g], [d,e], [a,b,c,f]]

Prolog: create a list of empty lists

I'm working on creating a board used for the Bert Bos puzzle, and I'm trying to represent the board as a list of lists.
I need to create a list of empty lists ex [ [], [] , [] , [] ] but the problem is I need the exact number of empty lists provided from the input. So for example if I give create_board(4,X), it should return X= [ [], [], [], [] ].
Here is what I have so far
generate_board(0, [[]]) :- !
generate_board(N, [[] | T]) :-
N =< 12, N >= 1,
N is N-1.
generate_board(N, T).
An easy way to create a list of a given length consisting of the same element, or just empty lists in this case, is to use maplist2:
generate_board(Length, Board) :-
length(Board, Length),
maplist(=([]), Board).
Here, maplist(=([]), Board) will call =([], Element) (the canonical form of [] = Element) for each Element in Board, thus unifying each element with []:
| ?- generate_board(4, L).
L = [[],[],[],[]]
yes
| ?-
You can extend this concept to do a two-dimensional empty board. Think of the board as a list of rows (with length Length) and each row as a list of elements (with length Width):
generate_board(Length, Width, Board) :-
length(Row, Width),
maplist(=([]), Row), % A row of empty lists, forming an empty row
length(Board, Length),
maplist(=(Row), Board). % A list of empty rows
| ?- generate_board(4,3, L).
L = [[[],[],[]],[[],[],[]],[[],[],[]],[[],[],[]]]
yes
| ?-
Here is just the reason why your program did not work (apart from the . in place of ,). Because this fragment fails, also your original program fails. You have to generalize the visible part somehow.
:- op(950,fy,*).
*_.
generate_board(0, [[]]) :- !
generate_board(N, _/*[[] | T]*/) :- % 2nd
* N =< 12, % 2nd
* N >= 1, % 2nd
N is N-1,
* generate_board(N, T). % 1st generalization
?- generate_board(4, B).
This method works for pure, monotonic Prolog programs. You have, however, used a cut which restricts generalization. In this case, one really has to pay attention not to generalize anything prior to the cut. The first generalization is thus the recursive goal. It is the very last goal in the clause. Only then, the other generalizations may take place
In your program without the cut, we could have generalized your program even further:
generate_board(0, _/*[[]]*/).
...
A simple solution:
generate_board(N, Board) :-
findall([], between(1, N, _), Board).
Apart from a couple of syntax errors, the main problem with your code is the line N is N-1. In Prolog, you cannot 're-assign' a variable. A variable has a single value throughout a predicate. 'N is N-1` can only succeed for a value which is equal to itself minus 1, which will obviously never be the case.
Fixing it is simple: just use a different variable for the reduced value:
generate_board(0, [[]]) :- !.
generate_board(N, [[] | T]) :-
N =< 12, N >= 1,
N2 is N-1,
generate_board(N2, T).
?- generate_board(4, X).
X = [[], [], [], [], []]
This gives a result, but it's one more element than intended. Can you figure out how to fix this yourself (hint: look at what the base case returns for input 0)

Find all positions of a value in a list in Prolog

My assignment is this: Write a program that reads an integer x and a list of integers L; then locate the list of all positions of x into L, and return the resulting list. For example, for x=2 and L=[1,2,3,4,2,5,2,6] the program should return the list R=[2,5,7].
So far, I've been able to write an indexOf predicate:
indexOf([E|_], E, 1).
indexOf([_|T], E, I) :- indexOf(T, E, I2), I is I2 + 1.
However, this doesn't "return" a list. So:
indexOf([a,b,c,a,d], a, R).
R = 1;
R = 4
I'd like to do something like this:
findAll([a,b,c,a,d], a, R).
R = [1, 4]
But I'm not sure how to collect the values into a list.
This is a school assignment, so I'd appreciate just a nudge in the right direction.
A nudge: you find the indices, but you don't collect them.
indices(List, E, Is) :-
indices_1(List, E, Is, 1).
For an empty list, the list of indices is empty,
and the element doesn't matter
indices_1([], _, [], _).
If the element is like the head, collect the index.
indices_1([E|Xs], E, [I|Is], I) :-
I1 is I + 1,
indices_1(Xs, E, Is, I1).
This needs another clause to work properly.
EDIT:
One way to do it would be:
indices_1([X|Xs], E, Is, I) :- dif(X, E),
I1 is I + 1,
indices_1(Xs, E, Is, I1).
In the previous clause, the head of the list and the Element are unified. In this clause, they are explicitly different. This means that only one of the two clauses can be true for an element of the list in the first arguemnt.
EDIT:
Another way to do that is to use findall and nth1:
indices(List, E, Is) :-
findall(N, nth1(N, List, E), Is).

Comparing lists items

I was wondering if you can help me in this Prolog program which should compare two lists' items and map them:
For example, I have got the two following lists:
A= [t1=v,[t2=w,[d3=a]],[d2=m,[d3=a]]]
B= [t11=v,t12=p,[t10=o,[t3=a,t22=w]],[t20=p,[t3=a,t22=m]]]
they are of the following (tentative) form:
is_plist([]).
is_plist([EL|ELs]) :-
is_el(EL),
is_plist(ELs).
is_el(_Name=_Value).
is_el(L) :-
is_plist(L).
So, I want to compare them based on the values occur after the equal signs, since I have got similar values such as v, a, m, etc. So the output would be something like
t1 = v -> t11=v
[t2=w,[d3=a]] -> [t10=o,[t3=a,t22=w]]
[d2=m,[d3=a]] -> [t20=p,[t3=a,t22=m]]
This is because the first two items of both lists got (v). The second item in the second list has different value, so it should be ignored. The second item in the first list is going to be mapped to the third one in list B since they both have w and a, etc.
I tried to split the problem into sub-problems and got the rules for getting the list’s members and collecting text after the equal signs but stuck in the comparison part. Can anyone help me in this?
%getting lists members:
m(X,[X|_]).
m(X,[_|R]) :- m(X,R).
%Collecting text rules:
c([], L, L).
c([H | T], L0, L2) :-
!,
c(H, L0, L1),
c(T, L1, L2).
c(_=C, L, [C | L]).
c(T, C) :-
c(T, [], C).

How does this permutation algorithm work

ar([],[]).
ar([p(_,_)|L],L1):-ar(L,L2),L1=L2.
ar([p(X,Y)|L],L1):-ar(L,L2),L1=[p(X,Y)|L2].
(p stands for point, having the coordinates X and Y)
Please help me to understand how the result is being constructed, especially the part where L1 gets a new value, thanks!
The definition of your predicate ar/2 behaves like the powerset function, being a syntactic variant of the following (where X is restricted to terms of p/2):
% clause 1: base case
ps([], []).
% clause 2: omit the element X
ps([_X|Y], Z) :-
ps(Y, Z).
% clause 3: keep the element X
ps([X|Y], [X|Z]) :-
ps(Y, Z).
The predicates ps/2 (and your ar/2) basically backtrack to bind all sub-lists of the list in the first argument to that of the second argument. It achieves this with the choice represented by the second and third clauses: either omit or keep a list element when constructing the new list.
Consider what Prolog does when executing the goal ps([a,b],L):
ps([_|[b]], Z) :- ps([b], Z). (via clause 2, drop a).
ps([b|[]], Z) :- ps([], Z). (via clause 2, drop b; note that [b] = [b|[]]).
ps([], Z) binds Z = [] (via clause 1, gives solution 1).
ps([b|[]], [b|Z]) :- ps([], Z). (via clause 3, keep b).
ps([], Z) binds Z = [] (via clause 1, gives solution 2).
ps([_|[b]], [a|Z]) :- ps([b], Z). (via clause 3, keep a).
ps([b|[]], Z) :- ps([], Z). (via clause 2, drop b).
ps([], Z) binds Z = [] (via clause 1, gives solution 3).
ps([b|[]], [b|Z]) :- ps([], Z). (via clause 3, keep b).
ps([], Z) binds Z = [] (via clause 1, gives solution 4).
Each of the deepest levels which hit the 'base-case' of clause 1 return up the call stack. Each of these cases result in the following:
Drop both a and b: []
Drop a, keep b: [b]
Keep a, drop b: [a]
Keep both a and b: [a,b]
Thus, we can backtrack to generate [], [b], [a] and [a,b], i.e., the four sub-lists of [a,b].
First of all, note that this procedure does not compute a permutation, but a sort of sublist: a list with "some" points removed, where by "some" is said in general form (one of the solutions is the empty list and also other solution is the original list), assuming the input list is well formed.
If the input list is not well formed (it has one item which is not a "point") then the procedure will fail.
Now let's explain the three clauses of ar/2, which is a recursive procedure:
First clause,
ar([], []).
states that if the first argument is the empty list, then the second argument is also the input list; i.e. for an empty list the only "sublist" conforming with the rules of the procedure is also an empty list.
This is also the base case of the recursive procedure.
The second clause,
ar([p(_,_)|L], L1):-ar(L, L2), L1=L2.
can be rewritten without using the L2 variable because it will eventually unify with L1:
ar([p(_,_)|L], L1):-ar(L, L1).
This clause is skipping the head of the input list and continuing with recursion. Upon return of recursion it will unify the resulting list (second argument of ar/2 call) with the second argument of the head of the clause.
The third clause,
ar([p(X,Y)|L], L1):-ar(L, L2), L1=[p(X,Y)|L2].
can be, again, rewritten without using the L2 variable by means of building the resulting list in the head of the clause:
ar([p(X,Y)|L], [p(X,Y)|L1]):-ar(L,L1).
This clause will take the head of the input list, continue recursion with the tail and then unify second argument of the head of the clause with the item taken and the resulting list of the recursion. That is, it will keep the item (head) of the input list along with the result of recursion.
Also note that this procedure is not reversible, if called with the first argument uninstantiated and the second argument instantiated it will loop forever.

Resources