我需要得到一个列表,如果矩阵中每个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.Matrix和submatrix
来创建此列表。该函数应具有以下模式:
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 :(得分: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
和N
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]