Reputation: 41
I am trying to extract a certain column(COLUMN) of index (K) from a list of lines (X).
This is the code I wrote so far:
extract(K,X,COLUMN):-
constructColumn(K,1,X,COLUMN).
constructColumn(K,B,X,COLUMN):-
nth1(B,X,LINE),
nth1(K,LINE,ELEMENTCOLUMN),
incr(B,B1),
constructColumn(K,B1,X,ELEMENTCOLUMN|COLUMN);
!.
incr(X, X1) :- X1 is X+1.
When I trace to see how it functions, I see that the new COLUMN list that I am building is not kept to give as an output at the end, it just outputs true. Is there a way for me to add elements to the predicate in a similar way?
Upvotes: 1
Views: 1292
Reputation: 60034
Just to show the modification required to make your code working:
extract(K,X,COLUMN):-
constructColumn(K,1,X,COLUMN).
constructColumn(K,B,X,[ELEMENTCOLUMN|COLUMN]):-
nth1(B,X,LINE),
nth1(K,LINE,ELEMENTCOLUMN),
succ(B,B1),
!,
constructColumn(K,B1,X,COLUMN).
constructColumn(_K,_B,_X,[]).
Let's explain: we use nth1(B,X,LINE)
to access every row, when it fails we're done. The first improvement could be to get rid of this access by index to rows: just let the list (of lists) control the recursion:
extract(_,[],[]).
extract(K,[LINE|LINES],[ELEMENTCOLUMN|COLUMN]):-
nth1(K,LINE,ELEMENTCOLUMN),
extract(K,LINES,COLUMN).
much better, isn't it ?
Upvotes: 0
Reputation: 58324
The maplist/3
predicate also works well here. maplist
will apply a predicate to a set of list arguments resulting in other list arguments, where that predicate is designed to work on one argument.
So you can write extract/3
as:
extract(ColNumber, Matrix, Column) :-
maplist(nth0(ColNumber), Matrix, Column).
And you're done. :)
| ?- extract(2, [[a,b,c,d],[e,f,g,h],[i,j,k,l]], R).
R = [c,g,k]
yes
| ?-
Upvotes: 3
Reputation: 12992
Since you have many iterations you could skip most of the writing by using findall/3
predicate:
extract(K,X,COLUMN):- findall(Elem , (member(X1,X), nth0(K,X1,Elem)) , COLUMN).
What the above does is for each X1 line (member of X lines) take the Kth element (using nth0/3
predicate) and store it to COLUMN list.
You can read about findall/3
here: www.swi-prolog.org/pldoc/man?predicate=findall/3
Example:
?- extract(1,[[1,2,3,4],[11,22,33,44],[111,222,333,444]],COLUMN).
COLUMN = [2, 22, 222].
?- extract(0,[[1,2,3,4],[11,22,33,44],[111,222,333,444]],COLUMN).
COLUMN = [1, 11, 111].
?- extract(2,[[1,2,3,4],[11,22,33,44],[111,222,333,444]],COLUMN).
COLUMN = [3, 33, 333].
?- extract(3,[[1,2,3,4],[11,22,33,44],[111,222,333,444]],COLUMN).
COLUMN = [4, 44, 444].
?- extract(5,[[1,2,3,4],[11,22,33,44],[111,222,333,444]],COLUMN).
COLUMN = [].
Upvotes: 0