【问题标题】:Create all the '' small'' matrix from a bigger one - Haskell从一个更大的矩阵创建所有的“小”矩阵 - Haskell
【发布时间】:2016-03-18 22:08:35
【问题描述】:

我有一个矩形矩阵,其中包含 B 或 N。矩阵示例:

g0 = [[B,B,B,B,B,B,N],
      [B,B,N,B,N,B,B],
      [N,B,N,N,N,N,N],
      [B,B,B,N,N,B,N],
      [N,N,N,B,B,B,B],
      [B,B,B,N,N,B,N]]

我有一个类似[Int,Int,Int,Int] 的矩形类型和一个函数,它可以从我的这种类型的矩阵中获取一个更小的矩形矩阵。这是函数,但这不是最重要的部分:

getRectangle :: Rectangle -> Grille -> Grille -- cette fonction récupère la grille qui correspond au rectangle donné
getRectangle (i,j,l,c) g = transpose (getLigne (j,c,(nbLigne (transpose g0))) (transpose (getLigne (i,l,(nbLigne g0)) g0)))
--transpose get create a matrix with (n,m) = (lines,columns) in a matrix (m,n) and nbLigne return the number of lines (or columns when used with transpose) of a matrix.

getLigne :: (Int,Int,Int) -> Grille -> Grille 
getLigne (i,l,0) g = []                     
getLigne (1,l,1) g = [head g]                
getLigne (i,l,indice) [] = []
getLigne (i,l,indice) g         
    | indice == (i+l) =  getLigne (i,l,(indice-1)) (init g) ++ [last g]
    | indice == i = [last g]
    | i < indice && indice < (i+l) = getLigne (i,l,(indice-1)) (init g) ++ [last g]
    | otherwise = getLigne (i,l,(indice-1)) (init g)

这是一个例子:

*Main> affiche (getRectangle (1,2,2,3) g0)
[B,B,B,B]
[B,N,B,N]
[B,N,N,N]

所以,我有一个带有(i,j,l,c) 的元组。知道1&lt;=i&lt;i+l&lt;=n1&lt;=j&lt;j+c&lt;=m 具有 n 矩阵的行数和 m 列数。 需要明确的是,使用元组(i,j,l,c),我的函数从我的矩阵中创建一个矩形,由这些情况组成:(i,j)(i+l,j)(i,j+c)(i+l,j+c)

现在我可以创建一个矩形,我需要在任何矩阵中创建所有可能的矩形。我对如何做到这一点一无所知,因为我觉得单个矩阵中有这么多矩形并且涵盖所有情况对我来说似乎非常困难和漫长。

也许我对某些点不太清楚,请随时提问。

【问题讨论】:

  • 这看起来像是列表推导的工作:枚举所有可能的矩形。您已经知道这些 4 元组必须满足哪些约束,因此您可以利用它们。
  • 确实列表推导可以完成这项工作,但我看不出如何涵盖所有问题。我有 4 个条件,所以似乎很难涵盖所有条件

标签: haskell matrix


【解决方案1】:

致敬 :),

对于组合,我经常使用列表单子。 请注意,像这样使用 do 表示法等同于使用列表推导

从一个位置你可以推断出所有可以起源于给定点的矩形:

allRectsOriginatingFrom :: Point -> Grille -> [Rectangle]
allRectsOriginatingFrom (x, y) g
    -- Si le point est dans ta grille...
    | (x >= 1 && x <= width g) && (y >= 1 && y <= height g) = do
        w <- [0 .. width g - x]
        h <- [0 .. height g - y]
        return (x, y, w, h)
    -- Sinon y'a pas de rectangle possible
    | otherwise = [] 

从那里,您只需将函数映射到网格上所有可能的位置:

allPointsOf :: Grille -> [Point]
allPointsOf g = do
    x <- [1 .. width g]
    y <- [1 .. height g]
    return (x, y)

allRectsOf :: Grille -> [Rectangle]
allRectsOf g = do
    pos <- allPointsOf g
    allRectsOriginatingFrom pos g

最后,使用您的 getLigne 函数映射它会得到您网格中的每个矩形。

PS:尝试创建数据类型而不是类型别名,我认为这样会更好(例如,创建像 data Rectangle = Rectangle Int Int Int Int 这样的数据类型而不是 type Rectangle = (Int, Int, Int, Int))。

【讨论】:

  • 谢谢,这正是我所需要的。所以,我只需要用getRectangle 映射它,但我怎样才能用映射绑定参数呢?说明:我得到:allGridOf :: [Rectangle] -&gt; [Grille] allGridOf x = map getRectangle g0 但它不起作用。我想在这里绑定g0。
  • 只要使用 lambda 函数(或者部分应用,如果可以的话)getAllSubGrids g = map (\ r -&gt; getRectangle r g) (allRectsOf g) 然后使用getAllSubGrids g0
猜你喜欢
  • 1970-01-01
  • 2015-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多