矩阵中所有2x2子矩阵中每个元素的总和

时间:2017-10-09 08:10:40

标签: haskell matrix

我需要得到一个列表,如果矩阵中每个2x2子矩阵的总和,偶数行和列。

例如,假设我们有一个4x4矩阵(1);函数应该如下计算它(我只想指出给定矩阵可以是任何nxm矩阵,其中n和m甚至是):

(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中实现它?

2 个答案:

答案 0 :(得分: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(当然还有MN s)矩阵转换为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]

答案 1 :(得分:0)

执行此任务的另一种方法是使用submatrix类型的Int -> Int -> Int -> Int -> Matrix a -> Matrix a函数,其中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]