【问题标题】:Prolog get squares of NxN matrixProlog 得到 NxN 矩阵的平方
【发布时间】:2018-06-12 17:41:46
【问题描述】:

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

我想获得组成列表的 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].

欢迎提出任何建议。谢谢

【问题讨论】:

  • 到目前为止你有什么尝试?
  • 我知道我需要什么,但是我不知道如何在 prolog 中编程,我的知识非常基础
  • 如果你在这个网站上搜索[prolog] matrix,你应该也会找到很多这样的想法。

标签: list matrix prolog


【解决方案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)。如果您手动执行其中一些操作,您会发现这相当于为两个坐标从 0 到行/列计数(减一)的所有排列添加 x 和 y 偏移量。
  4. 现在您已经建立了这种关系,您需要进行迭代并组装您的输出。我认为maplist/N 就足够了。

希望这会有所帮助!

【讨论】:

  • 也许,square_matrix(M, Degree) :- length(M, Degree), maplist(flip(length,Degree), M).(和flip(A,B,C):- call(A,C,B).)? (在 RosettaCode 的 Zebra 页面上看到 flip...)
  • @WillNess 聪明!
猜你喜欢
  • 2016-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-15
  • 2022-12-12
相关资源
最近更新 更多