2017-10-09 306 views
0

如果矩阵中的每个2x2子矩阵具有偶数行和列,我需要得到一个列表。例如,假设我们有一个4×4的矩阵(1);该函数应该计算它像以下(我只是想指出的是,给定的矩阵可以是任意的n×m矩阵,其中n和m甚至):来自矩阵的所有2x2子矩阵中的每个元素的总和

(1): [ [1, 2, 3, 4], 
     [5, 6, 7, 8], 
     [9, 10,11,12], 
     [13,14,15,16] ] 

sum2x2 of (1): 
    1. 1+2+5+6 = 14 
    2. 3+4+7+8 = 22 
    3. 9+10+13+14 = 46 
    . 
    . 


result: [14, 22, 46, ...] 

我想用Data.Matrixsubmatrix创建这个清单。而功能应具有以下模式:

sum2x2 :: Matrix Double -> [Double] 

我已经开始写这个功能,但我不知道如何从这里着手:

sum2x2 :: Matrix Double -> [Double] 
sum2x2 m = if even (ncols m) && even (nrows m) 
    then what? 
    else error "sum2x2 takes only even matrices" 

submatrix作品像下面这样:

-- | /O(1)/. Extract a submatrix given row and column limits. 
-- Example: 
-- 
-- >     (1 2 3) 
-- >     (4 5 6) (2 3) 
-- > submatrix 1 2 2 3 (7 8 9) = (5 6) 
submatrix :: Int --^Starting row 
      -> Int --^Ending row 
      -> Int --^Starting column 
      -> Int --^Ending column 
      -> Matrix a 
      -> Matrix a 

所以,我有这个概念。我如何使用列表理解在Haskell中实现?

+0

'Data.Matrix'封装包括很好[分裂块(https://hackage.haskell.org/package/matrix-0.3.5.0/docs/Data-Matrix.html#g:8)功能像“子矩阵”。他们是这项工作非常方便的工具。 – Redu

回答

5

刚刚使用sum函数的矩阵,因为它是Foldable的实例呢?

import Data.Matrix 

sum2x2 :: Matrix Double -> Double 
sum2x2 m = if even (ncols m) && even (nrows m) 
    then sum m 
    else error "sum2x2 takes only even matrices" 

main :: IO() 
main = print $ sum2x2 (fromList 2 2 [1..]) 

本例创建一个矩阵((1, 2), (3, 4))并返回总和10。我猜,sum2x2的类型应该是sum2x2 :: Matrix Double -> Double而不是sum2x2 :: Matrix Double -> [Double]

您可能还会发现splitBlocks函数有用。

splitBlocks 2 2 matrix4x4 

创建(Matrix a, Matrix a, Matrix a, Matrix a)类型的元组,这是你要找的矩阵。

如果问题是任何M x N(甚至M S和N。肯定)矩阵转换成的2 x 2矩阵列表,然后将下面的实现可能会有所帮助:

to2x2Martices m = 
    [submatrix x1 x2 y1 y2 m | (x1, x2) <- rawPairs, (y1, y2) <- columnPairs] 
    where 
    pairs [] = [] 
    pairs (x:y:xs) = (x, y) : pairs xs 

    rawPairs = pairs [1..(nrows m)] 
    columnPairs = pairs [1..(ncols m)] 

的逻辑是迭代每行对和列中的每一对,并获得这些对的2 x 2矩阵。

它把下面的矩阵:

( 1 2 3 4) 
( 5 6 7 8) 
( 9 10 11 12) 
(13 14 15 16) 

分为以下列表:

[( 1 2) 
( 5 6) 
,( 3 4) 
( 7 8) 
,( 9 10) 
(13 14) 
,(11 12) 
(15 16) 
] 

因此,你可以在地图的列表,并获得总和的每一个元素。

map sum $ to2x2Martices (fromList 4 4 [1..]) 

评估为[14,22,46,54]

+0

但OP想要计算每个2x2 **子**矩阵的总和。 –

+0

准确地说,我知道我可以很容易地从n×m矩阵中得到一个2x2子矩阵的总和,其中n和m是偶数,但是如何获得给定矩阵中每个2x2子矩阵的和的列表?我怎样才能以某种方式使用splitBlocks,以便对于一个nxm矩阵,我可以得到矩阵内所有2x2子矩阵的列表? –

+0

这是要走的路,不知道splitBlocks,而且看起来很方便。谢谢! – Netwave

0

做这个工作是使用Int -> Int -> Int -> Int -> Matrix a -> Matrix asubmatrix函数,其中Int型的前4个参数开始行,结束行,起始列的另一种方式,结束柱。

import Data.Matrix 
subsums :: Matrix Int -> [Int] 
subsums m = let subs = map (\(x,y) -> (x,x+1,y,y+1)) $ (,) <$> [1,3..nrows m] <*> [1,3..ncols m] 
      in map (\(rs, re, cs, ce) -> sum (submatrix rs re cs ce m)) subs 

*Main> subsums . fromLists $ [[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]] 
[14,22,46,54]