0
votes

I have a matrix of 6x6 numbers and I'm writing a prolog code that gives me the numbers in a certain row, column or square. For instance:

   0n 1n 2n 3n 4n 5n
0n [[1,2,3,4,5,6]
1n [2,3,4,5,6,1]
2n [3,4,5,6,1,2]
3n [4,5,6,1,2,3]
4n [5,6,1,2,3,4]
5n [6,1,2,3,4,5]]

I already have code for rows and columns, which is something like:

row(1,[A|_],A).
row(Y,[_|B],X) :-
    Y-1 is Y1,
    row(Y1,B,X).

But now I'm stuck on how to generate a 3x3 square. I want to work with coordinates, so the first argument should be something like (1,3) and it will give the square of row 1n and column 3n, then the matrix as the second and the numbers in the square as third argument. Does anyone have any tips? I was thinking I might have to work with a head tail pattern again; getting the first three numbers of the given row/column, then doing this three times, but I don't know how or if this is possible and effective.

Any comments are greatly appreciated!

1
No need to work with that pattern in the first case either. Prolog has an nth1/3 predicate.Willem Van Onsem

1 Answers

0
votes

First of all, your predicate to obtain the row, is not safe:

row(1,[A|_],A).
row(Y,[_|B],X) :-
    Y-1 is Y1,
    row(Y1,B,X).

In case I query for row(0,[1,4,2,5],X). it will get stuck into an infinite loop immediately, in case i work with row(2,[1,4,2,5]). it will first give me the correct result, but then get into an infinite loop when searching for more answers.

A better approach would be:

row(1,[A|_],A).
row(Y,[_|B],X) :-
    Y > 1,
    Y-1 is Y1,
    row(Y1,B,X).

Since now the Y > 1 guards the fact that you will not perform recursion if Y is less than or equal to 1.

That being said, you do not need to construct this predicate yourself: most Prolog interpreters already have such a predicate: nth1/3:

nth1(?Index, ?List, ?Elem)

Is true when Elem is the Index'th element of List. Counting starts at 1.

If you can assume that this predicate exists, you can use:

elem(I,J,Matrix,Cell) :-
    nth1(I,Matrix,Row),
    nth1(J,Row,Cell).

Where I is the number of the row, and J the number of the column we wish to fetch.

In case it does not exists, I suggest renaming your row/3 predicate to nth1/3 since it is equivalent.

In case you want to start counting at 0 (which the top of your question suggests), you can use nth0/3 instead of nth1/3.