2017-10-09 2 views
0

짝수 행과 열이있는 행렬에 각 2x2 부분 행렬의 합계가 있으면 목록을 가져와야합니다.행렬의 모든 2x2 부분 행렬의 각 원소의 합

예를 들어, 4x4 매트릭스 (1)가 있다고 가정하십시오.

(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가 만드는 : 함수는 (난 그냥 주어진 행렬은 n과 m도을있는 모든 N × M 개의 행렬이 될 수 있습니다 싶습니다 ) 다음처럼 계산한다 이 목록. 그리고 함수는 다음 패턴해야한다 :이 기능을 쓰기 시작했다

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 :: Matrix Double -> [Double] 대신 sum2x2 :: Matrix Double -> Double이어야합니다.

유용한 기능은 splitBlocks입니다.

splitBlocks 2 2 matrix4x4 

당신이 찾고있는 행렬이다 유형 (Matrix a, Matrix a, Matrix a, Matrix a)의 튜플을 작성합니다. 문제가 2 x 2 행렬의 목록에 매트릭스 (심지어 M들과 N들과 확실히) 어떤 M x N를 변환하는 경우

, 다음 구현은 도움이 될 수 있습니다

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..]) 

는 종료

+0

그러나 OP는 모든 2x2 ** sub ** 매트릭스의 합계를 계산하려고합니다. –

+0

정확히, n과 m이 짝수 인 nxm 행렬에서 하나의 2x2 부분 행렬의 합을 쉽게 얻을 수 있지만 주어진 행렬의 2x2 부분 행렬 각각에 대한 합계 목록을 얻는 방법은 알고 있습니다. 어떻게 splitblock을 사용하여 nxm 행렬에 대해 행렬 내의 모든 2x2 부분 행렬 목록을 얻을 수 있습니까? –

+0

이것이 갈 방법이며, splitBlocks에 대해 몰랐고, 매우 편리하게 보입니다. 감사! – Netwave

0

Int 유형의 처음 4 개 매개 변수 행을 시작하는 행을 종료 칼럼을 시작 유형 Int -> Int -> Int -> Int -> Matrix a -> Matrix asubmatrix 기능을 사용하는 것이 일을하는 또 다른 방법, [14,22,46,54]로 평가 기둥.

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]