1

I worked all afternoon on a simple thing but cannot seem to get it right for some reason : how to turn a list into a matrix of given width.

Example : I got a list such as

[1, 3, 5, 7, 6, 8, 9, 0]

and want to create a matrix such as

[[1, 3],
 [5, 7],
 [6, 8],
 [9, 0]]

through a predicate

list2matrix/3 : list2matrix(List, Size_of_Rows, Matrix).

In this example used like :

list2matrix([1, 3, 5, 7, 6, 8, 9, 0], 2, Matrix).

The predicate should fail if the length of the list is not a multiple of the size of the rows.

I decided not to post my work since I think I got it so wrong that it would not help me to get correction on it ;(

Thanks by advance if you can propose any leads about how to deal with such a problem.

false
  • 10,264
  • 13
  • 101
  • 209
m09
  • 7,490
  • 3
  • 31
  • 58
  • 2
    Your problem statement is incomplete. Shall `list2matrix([1, 3, 5], 2, Matrix)` succeed or fail? And in case of success, shall `[5]` be dropped or extended to `[5,_]` or whatever other value. – false Nov 03 '11 at 18:32
  • let's say it'd fail, thanks for pointing that out. Since I intend on using it on list with square lengthes I didn't precise ;( – m09 Nov 03 '11 at 18:41

3 Answers3

2

You can divide the problem in two parts. The first building block would be to build a row of N elements. That is to take the input list and split it in two lists, one will have exactly N elements (the row) and the other is the remaining of the input list.

The second building block would be to build the matrix which is made of rows.

list_to_matrix([], _, []).
list_to_matrix(List, Size, [Row|Matrix]):-
  list_to_matrix_row(List, Size, Row, Tail),
  list_to_matrix(Tail, Size, Matrix).

list_to_matrix_row(Tail, 0, [], Tail).
list_to_matrix_row([Item|List], Size, [Item|Row], Tail):-
  NSize is Size-1,
  list_to_matrix_row(List, NSize, Row, Tail).
gusbro
  • 22,357
  • 35
  • 46
  • Thanks a lot for your answer, I'm trying to understand it and will test it soon, I'll comment after that :) – m09 Nov 03 '11 at 18:42
  • Ok ok, I read it and understood it quite easily, though I still think I'd have had a hard time finding a solution by myself :( I just added :- !. to cut backtracking after each first choice so that it's deterministic and now I have what I wanted, thank you a lot :) – m09 Nov 03 '11 at 18:50
  • 3
    Your `list_to_matrix_row` can be simplified to `list_to_matrix_row(L, RowLen, Row, Rest) :- length(Row, RowLen), append(Row, Rest, L).` – Fred Foo Nov 04 '11 at 11:22
  • You 're right!. However I believe it is easier to understand with this recursive procedure. – gusbro Nov 04 '11 at 14:24
2

BTW, I thought I'd mention the code I finally wrote :

length_(Length, List) :- length(List, Length).

list2matrix(List, RowSize, Matrix) :-
    length(List, L),
    HowManyRows is L div RowSize,
    length(Matrix, HowManyRows),
    maplist(length_(RowSize), Matrix),
    append(Matrix, List).

It's more high order oriented and funnier to read I guess :)

m09
  • 7,490
  • 3
  • 31
  • 58
  • 1
    Interesting! With [`library(lambda)`](http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl) you could write `maplist({RowSize}+\Xs^length(Xs,RowSize), Matrix)` instead of using an auxiliary definition. See [this intro](http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord). – false Dec 12 '11 at 23:44
1

Look for a pattern in your desired outcome. That means pair numbers will be allocated as the second number in each pair and non pairs will be in first place each time. Create a bi dimensional array and assign non pair positions to sub index "a" and pairs to "b".

As you could see "i" is an index for an array, a multidimensional array. i[a][b]

You need to iterate through both arrays in order to accomplish this.

Hope it helps.

Cristobal
  • 61
  • 2
  • 3
  • the problem I got when doing it this way is that it's fine for 2 as width of the matrix but not for any number instead of 2. In my case I'm interested in particular in transforming a list whose length is 81 into a 9*9 matrix. I'd like the resulting predicate to be size-hardcoding free but if 9 gotta be hardcoded then it's ok ! – m09 Nov 03 '11 at 18:06