2017-01-18 5 views
10

行列内で最大の連続した数値を返すRコードを記述しようとしています。連続ペアは水平、垂直、両方の対角線になります。例えば ためR:行列内で最大の連続した数値を返します。

iが行列している場合:

ma = array(c(8,4,3,1,7,5,9,15,6,10,16,11,2,14,12,13), dim = c(4,4)) 

(1)水平方向の最高連続ペア:16及び12; (2)垂直:16と11(3)対角線():16と13; (4)対角(/):16と15

Rでこれを行うにはどうすればよいですか?

+3

'のS < - MA [1:3] + MA [2:4]。 (s == max(s)、arr.ind = TRUE) '行の最初のペアのインデックスを取得します。そのペアはそのすぐ下にあります。列の場合は、コンマを反転するだけです。対角線はもう少し作業になります。 – alistaire

+1

対角線は 's < - ma [1:3,1:3] + ma [2:4,2:4]でなければなりません。これは(s == max(s)、arr.ind = TRUE) 'いいえ? – BonStats

+0

あなたは最大の合計で連続したペアをお探しですか?それ以外の場合は、どのようにペアを比較しますか? – C8H10N4O2

答えて

1

ここでは、行列演算を使用した解法があります。多くの場合、行と列、特に大きな行列のネストループよりも効率的です。

directionalSums <- function(x){ 
    stopifnot(is.matrix(x)) 

    # padding functions to allow matrix addition 
    padL <- function(x) cbind(-Inf,x) 
    padR <- function(x) cbind(x,-Inf) 
    padU <- function(x) rbind(-Inf,x) 
    padD <- function(x) rbind(x,-Inf) 

    # these padding functions are just for readability 
    padLU <- function(x) padL(padU(x)) 
    padLD <- function(x) padL(padD(x)) 
    padRU <- function(x) padR(padU(x)) 
    padRD <- function(x) padR(padD(x)) 

    m <- nrow(x) 
    n <- ncol(x) 

    sumR <- padR((padL(x) + padR(x))[1:m,2:n]) 
    sumD <- padD((padU(x) + padD(x))[2:m,1:n]) 
    sumRD <- padRD((padLU(x) + padRD(x))[2:m,2:n]) 
    sumRU <- padRU((padRU(x) + padLD(x))[2:m,2:n]) 

    list(`right`=sumR, 
     `down`=sumD, 
     `right and down`=sumRD, 
     `right and up`=sumRU) 

} 

試してみましょう。

(sumList <- directionalSums(ma)) 

maxLocList <- lapply(sumList, function(x) which(x==max(x), arr.ind=TRUE)) 

for (i in 1:length(maxLocList)){ 
    nameD <- names(maxLocList)[i] 
    startCell <- maxLocList[[i]] 
    maxSum <- sumList[[i]][startCell] 
    x1 <- ma[startCell] 
    x2 <- maxSum - x1 
    writeLines(paste0('The max-sum consec. pair going ', 
        nameD, ' starts at [', 
        paste(startCell, collapse=', '), 
        '], with sum ', maxSum, 
        ' and components ', x1, ' and ',x2) 
      ) 
} 

戻り値:

$right 
    [,1] [,2] [,3] [,4] 
[1,] 15 13 8 -Inf 
[2,] 9 15 24 -Inf 
[3,] 12 25 28 -Inf 
[4,] 16 26 24 -Inf 

$down 
    [,1] [,2] [,3] [,4] 
[1,] 12 12 16 16 
[2,] 7 14 26 26 
[3,] 4 24 27 25 
[4,] -Inf -Inf -Inf -Inf 

$`right and down` 
    [,1] [,2] [,3] [,4] 
[1,] 13 17 20 -Inf 
[2,] 13 21 22 -Inf 
[3,] 18 20 29 -Inf 
[4,] -Inf -Inf -Inf -Inf 

$`right and up` 
    [,1] [,2] [,3] [,4] 
[1,] -Inf -Inf -Inf -Inf 
[2,] 11 11 12 -Inf 
[3,] 8 19 30 -Inf 
[4,] 10 31 23 -Inf 

The max-sum consec. pair going right starts at [3, 3], with sum 28 and components 16 and 12 
The max-sum consec. pair going down starts at [3, 3], with sum 27 and components 16 and 11 
The max-sum consec. pair going right and down starts at [3, 3], with sum 29 and components 16 and 13 
The max-sum consec. pair going right and up starts at [4, 2], with sum 31 and components 15 and 16 
0

ここでは単純な(ただし長い)コードを使用して行う方法があります。

最大の連続を持つペアを探しているので、最初にセルを取り、すべての連続する合計を見つける関数を作成する必要があります。

consec <- function(ma,y,x){ 
    return(
    c(if(x<ncol(ma))    ma[y,x] + ma[y,x+1], 
     if(x>1)      ma[y,x] + ma[y,x-1], 
     if(y<nrow(ma))    ma[y,x] + ma[y+1,x], 
     if(y>1)      ma[y,x] + ma[y-1,x], 
     if(x<ncol(ma) & y<nrow(ma)) ma[y,x] + ma[y+1,x+1], 
     if(x>1 & y<nrow(ma))  ma[y,x] + ma[y+1,x-1], 
     if(x<ncol(ma) & y>1)  ma[y,x] + ma[y-1,x+1], 
     if(x>1 & y>1)    ma[y,x] + ma[y-1,x-1]) 
) 
} 

境界のセルが連続して対を形成するために以下の8人の隣人を持っていますので、この機能(if文)の左半分は、我々は境界の外に出ていないことを確認します。その後、右半分は連続したペアの合計を取得し、それをリストに追加します。

ここでconsec(ma, 3, 2)を使用すると、ma[3,2]の連続の和のベクトルが得られます。

次に、各セルの最高連続合計を持つ2番目の行列を埋めたいとします。次のコードを使用して、正しい次元の空白行列を作成できます。

ma2 <- matrix(0, nrow = nrow(ma), ncol = ncol(ma)) 

今ループと以前に作成したconsec機能を使用してそれを埋めます。

for(i in 1:nrow(ma)){ 
    for(j in 1:ncol(ma)){ 
    ma2[i,j] <- max(consec(ma,i,j)) 
    } 
} 

今、私たちは、連続した和の私たちの行列を持っていることを、我々はそれで最大の合計を見つけることができ、そしてそれの座標は、我々は元の行列に見てみたい場所に対応します。最大値である数値のいずれか一方のみペアが存在する場合

ma.max <- which(ma2 == max(ma2), arr.ind = TRUE) 

さて、次にma.max 2行(同じ対の2つの置換)を有するであろう。

ma[ma.max[1,1], ma.max[1,2]]; ma[ma.max[2,1], ma.max[2,2]] 

表示するには:この場合、1516が得られます。

最大値がある場合は、上記のコードの数値を大きくして次のペア(3と4)を取得するなどのようにします。対角の連続を望まない場合など、リストの最後の4行を削除する場合など、consec関数を微調整することさえできます。

関連する問題