Prolog - returns the nth row of the matrix

I am trying to write a predicate rowN/3 that returns the nth element (in this case a row) of a matrix. Example:

 ?- rowN([[1,2],[3,4],[5,6]], 2, R). R = [3,4]; No 

I struggle with the stance. I tried unsuccessfully to find several similar examples. So far I have managed to write the following:

code:

 rowN(L,[],[]). rowN([],X,[]). rowN([],[],[]. rowN([H|T],X,R) :- A==X, A is A + 1, rowI(T,A,H). 
+5
source share
1 answer

This line does not make much sense:

 rowN(L,[],[]). 

because the second argument is an integer (if I understand correctly), and you use a list. This applies to almost all of your arguments. Also, are you using RowI in your recursive call?

Decision

The solution is to first indicate that the first row ( I = 1 ) is equal to the head of the matrix:

 rowN([H|_],1,H). 

Next you need to find an iterative way to list through your matrix. So, the header definitely takes the form:

 rowN([H|T],I,X) :- # ... 

Now we will assume that I not equal to 1 (we will discuss this issue later). In this case, we need to go further along the matrix, so we take the tail and return the counter I back. This can be done using:

 rowN([_|T],I,X) :- I1 is I-1, rowN(T,I1,X). 

So our predicate reads:

 rowN([H|_],1,H). rowN([_|T],I,X) :- I1 is I-1, rowN(T,I1,X). 

Now, if you use this predicate, it will give the correct result:

 ?- rowN([[1,2],[3,4],[5,6]], 2, R). R = [3, 4] ; false. 

The question is why the predicate does not generate other results: after showing the first result for rowN([[1,2],[3,4],[5,6]], 2, R) :- rowN([[3,4],[5,6]],1,[3,4]). he may try to find alternatives. He does this using the second sentence, but then it will eventually end up in rows and call the predicate rowN([],_,_) , since not from cluster matches, he will fail.

This solution is not perfect: it does not work in all directions correctly, which is generally difficult in Prolog. This is why good Prolog programmers have written libraries.

Using builtin nth1/3

Instead of reinventing the wheel, you can use the nth1/3 predicate in swi-prolog. Although the arguments are reversed - you need to call it nth1(2,[[1,2],[3,4],[5,6]],R). - it has the advantage that it works in more directions, that most people can come up with a quick solution, but with some probability of bugfree (since it has been tested billions of times for all Prolog programs that use the predicate), and some of these built-in functions are implemented in C ++, which makes them sometimes faster. For instance:

 ?- nth1(2, [[1,2],[3,4],[5,6]], R). R = [3, 4]. ?- nth1(I, [[1,2],[3,4],[5,6]], [5,6]). I = 3. ?- nth1(I, [[1,2],[3,4],[5,6]], R). I = 1, R = [1, 2] ; I = 2, R = [3, 4] ; I = 3, R = [5, 6]. ?- nth1(I,M,[2,3]). I = 1, M = [[2, 3]|_G23] ; I = 2, M = [_G22, [2, 3]|_G26] ; I = 3, M = [_G22, _G25, [2, 3]|_G29] ; I = 4, M = [_G22, _G25, _G28, [2, 3]|_G32] . 

So you can ask what the second row is, ask where row [5,6] , make the query more general by responding with tuples of index I and row R and generate a matrix with row [2,3] somewhere.

+4
source

Source: https://habr.com/ru/post/1237696/


All Articles