2017-10-09 20 views
0

偶数の行と列を持つ行列の各2x2部分行列の合計を求める必要があります。行列から2x2のすべての部分行列の各要素の和

たとえば、4x4行列(1)があります。この関数は(私は与えられた行列は、nおよびmがさえある任意の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でこれを実装するにはどうすればよいですか?

+0

'Data.Matrix'パッケージがいい[分割ブロック(https://hackage.haskell.org/package/matrix-0.3.5.0/docs/Data-Matrix.html#g:8)機能を含みます「サブマトリックス」のように。彼らはこの仕事のための非常に便利なツールです。 – Redu

答えて

5

sum関数を使用するのは、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 sおよびN sの)任意のM x N2 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..]) 

この仕事を行うためのもう一つの方法は、Intタイプの第4のパラメータは、行を開始する行を終了列を開始、終了されるタイプInt -> Int -> Int -> Int -> Matrix a -> Matrix asubmatrix関数を使用することであろう[14,22,46,54]

+0

しかしOPは2x2 **サブ**マトリックスの合計を計算したいと考えています。 –

+0

正確には、nとmが偶数であるnxm行列から1つの2x2部分行列の和を簡単に得ることができますが、与えられた行列の各2x2部分行列の和のリストを取得するにはどうすればよいでしょうか?どのようにしてsplitblockを使うことができるのですか?nxmの行列の場合、行列内の2x2の部分行列のリストを得ることができますか? –

+0

これは行く方法です、splitBlocksについて知らなかった、と非常に便利だね。ありがとう! – Netwave

0

に評価カラム。

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] 
関連する問題