Prolog得到NxN矩阵的正方形

时间:2018-06-12 17:41:47

标签: list matrix prolog

我有一个列表L = [[5,6,7,8],[10,11,12,13],[1,2,3,4],[14,15,16,17]] Ii。这代表了我的矩阵。大小可以改变动态,因此块大小可以不同,4x4 = 4个元素,9x9 = 9个元素

我想获得组成List的4个方格。(在这种情况下,它是4乘4的矩阵)。如果我有那个矩阵:

5  6  7  8
10 11 12 13
1  2  3  4
14 15 16 17 

结果应为:

R = [5,6,10,11],[7,8,12,13],[1,2,14,15],[3,4,16,17].

欢迎任何建议。谢谢

1 个答案:

答案 0 :(得分:1)

您需要的第一件事就是将列表列表转换为矩阵的杠杆。什么区分二维矩阵与列表列表?坐标系的想法。因此,您需要一种方法坐标对与矩阵中的相应值相关联。

at(Matrix, X, Y, V) :- nth0(X, Matrix, Row), nth0(Y, Row, V).

这个谓词可以在(X,Y)处索引矩阵并得到值V.这就是IMO,它是Prolog强大之处的大量演示,因为一旦你有了这个,简单的谓词,你获得:

  • 在提供的点获取值的能力:

    ?- at([[5,6,7,8],[10,11,12,13],[1,2,3,4],[14,15,16,17]], 1,3, V).
    V = 13.
    
  • 迭代整个矩阵的能力(仅实例化Matrix并将其他参数保留为变量):

    ?- at([[5,6,7,8],[10,11,12,13],[1,2,3,4],[14,15,16,17]], X,Y, V).
    X = Y, Y = 0,
    V = 5 ;
    X = 0,
    Y = 1,
    V = 6 ;
    ...
    X = 3,
    Y = 2,
    V = 16 ;
    X = Y, Y = 3,
    V = 17.
    
  • 搜索矩阵中值的功能:

    ?- at([[5,6,7,8],[10,11,12,13],[1,2,3,4],[14,15,16,17]], X,Y, 14).
    X = 3,
    Y = 0 ;
    false.
    

所以这是一个非常有用的杠杆!在传统的语言中,你需要三个不同的函数来完成所有这些事情,但这是不同的,因为在Prolog中我们只需要在事物之间定义关系(在这种情况下,数据结构)和一个坐标对)和Prolog可以做很多繁重的工作。

现在很容易看到我们如何通过定义我们希望看到的X和Y值的集合来生成特定的子矩阵。例如,要获得左上角矩阵,我们会这样做:

?- between(0,1,X), between(0,1,Y), 
   at([[5,6,7,8],[10,11,12,13],[1,2,3,4],[14,15,16,17]], X,Y, V).
X = Y, Y = 0,
V = 5 ;
X = 0,
Y = 1,
V = 6 ;
X = 1,
Y = 0,
V = 10 ;
X = Y, Y = 1,
V = 11.

我们当然可以使用findall/3在一个地方收集解决方案:

?- findall(V, (between(0,1,X), between(0,1,Y), 
               at([[5,6,7,8],[10,11,12,13],[1,2,3,4],[14,15,16,17]], X,Y, V)),
           Vs).
Vs = [5, 6, 10, 11].

你的问题还剩下一些算法。让我们看看我们是否有一个方阵:

square_matrix(M, Degree) :-
    length(M, Degree),
    maplist(length, M, InnerDegrees),
    forall(member(I, InnerDegrees), I=Degree).

这不是一个完美的谓词,因为它不会产生!但是它会告诉我们矩阵是否是正方形,如果是,它有多大程度:

?- square_matrix([[5,6,7,8],[10,11,12,13],[1,2,3,4],[14,15,16,17]], D).
D = 4.

一旦你拥有了,你需要做的就是公式化:

  1. 确保学位是一个完美的正方形
  2. 取学位的平方根。这是你有多少行或列(平方根4 = 2,2行2列,平方根9 = 3,3行3列)。
  3. 在(行,列)坐标与该位置矩阵的(x,y)坐标的列表之间建立关系。例如,在4x4矩阵中,您有四个图块:(0,0),(0,1),(1,0)和(1,1)。 (0,0)的坐标为(0,0),(0,1),(1,0),(1,1),但(1,1)的坐标为(2,2) ,(2,3),(3,2),(3,3)。如果您手动执行其中的一些操作,您将看到它将相当于为两个坐标添加x和y偏移到从0到行/列计数(减去1)的所有排列。
  4. 现在您已经拥有了这种关系,您需要进行迭代并组装输出。我认为maplist/N就足够了。
  5. 希望这有帮助!