2017-10-09 124 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]