2014-12-24 45 views

回答

2

這裏有一個解決方案,而相同的元素,並反覆求和哪些方形n通過n陣列輔助工作,甚至n中間陣列(只是蠻力索引樂趣):

import numpy as np 

def sum_shells(a): 
    n = len(a) 
    no2 = n // 2 
    shell_sums = [] 
    for i in range(no2): 
     shell_sums.append(np.sum(a[i,i:n-i]) + np.sum(a[n-i-1,i:n-i]) + 
          np.sum(a[i+1:n-i-1,i]) + np.sum(a[i+1:n-i-1,n-i-1])) 
    if n % 2: 
     shell_sums.append(a[no2, no2]) 
    return shell_sums 

a = np.array([ 
    [8, 0, 7, 4, 3, 0, 0, 7, 6, 9], 
    [8, 1, 0, 6, 3, 4, 2, 1, 4, 6], 
    [8, 5, 9, 6, 8, 0, 0, 1, 3, 0], 
    [3, 2, 8, 9, 5, 8, 6, 5, 6, 7], 
    [6, 7, 5, 1, 1, 0, 5, 1, 9, 0], 
    [8, 9, 4, 5, 9, 7, 0, 0, 0, 4], 
    [7, 9, 6, 7, 4, 7, 5, 1, 7, 4], 
    [6, 8, 2, 6, 1, 9, 8, 5, 2, 1], 
    [9, 1, 1, 3, 7, 6, 8, 0, 8, 7], 
    [2, 8, 6, 3, 6, 5, 0, 3, 1, 8] ]) 

b = np.array([[9, 5, 8, 6, 5], 
       [1, 1, 0, 5, 1], 
       [5, 9, 7, 0, 0], 
       [7, 4, 7, 5, 1], 
       [9, 5, 0, 2, 3] ]) 
print(sum_shells(a)) 
print(sum_shells(b)) 

產地:

[170, 122, 85, 62, 17] 
[67, 31, 7] 
+0

你實際上是在創造大量的小型中間陣列......當你做了'sum(a [i,i:n-i] + a [n-i-1,i:n-i])',numpy分配一個新的n-2 * i'項目數組,並用它的兩個元素的元素和來填充它。這當然很容易避免,加上可能不可忽視的加速度,在將它們加在一起之前,通過對每個切片進行求和來完成。你也應該使用'np.sum'而不是標準庫的'sum'。 – Jaime

+0

@Jaime - 當然你說的對,這裏我有點不小心。我編輯了建議的代碼。謝謝。 – xnx

0

我有個主意。第一次找到整個10 * 10數組的總和,然後找到內部9 * 9數組的總和。然後減法是外層和的結果。

for i in range(len(A)/2): 
    B = A[1:-1, 1:-1] 
    print sum(A)-sum(B) 
    A = B 

一個循環將找到所有的總和。

可能有更好的方法來做到這一點..

2

如果你知道如何在中間(2n)*(2n)平方的總和,那麼它很容易:取(2n)*(2n)平方的總和,然後減去裏面的(2n-2)*(2n-2)平方的總和;所不同的是在邊界上的元素的和(即,是在外部正方形的,但不在內):

import numpy 

# let x be a 10 * 10 array 
x = numpy.array([ 
    [8, 0, 7, 4, 3, 0, 0, 7, 6, 9], 
    [8, 1, 0, 6, 3, 4, 2, 1, 4, 6], 
    [8, 5, 9, 6, 8, 0, 0, 1, 3, 0], 
    [3, 2, 8, 9, 5, 8, 6, 5, 6, 7], 
    [6, 7, 5, 1, 1, 0, 5, 1, 9, 0], 
    [8, 9, 4, 5, 9, 7, 0, 0, 0, 4], 
    [7, 9, 6, 7, 4, 7, 5, 1, 7, 4], 
    [6, 8, 2, 6, 1, 9, 8, 5, 2, 1], 
    [9, 1, 1, 3, 7, 6, 8, 0, 8, 7], 
    [2, 8, 6, 3, 6, 5, 0, 3, 1, 8], 
]) 

for i in xrange(1, 6): # loop with i = 1,...,5 
    # find the sum of the (2i)*(2i) square in the middle 
    a = numpy.sum(x[5-i:5+i, 5-i:5+i]) 

    # find the sum of the (2i-2)*(2i-2) square in the middle 
    b = numpy.sum(x[6-i:4+i, 6-i:4+i]) 

    # the difference gives the sum of the elements on the border 
    s = a - b 
    print s 
2

下面的代碼計算每個圖層,然後從中減去較小的圖層。這是相當普遍的,所以任何大小爲N * N的數組都應該能夠傳遞給它,只要N是偶數(我認爲)。

import numpy as np 

arr = np.array([[8, 0, 7, 4, 3, 0, 0, 7, 6, 9], 
       [8, 1, 0, 6, 3, 4, 2, 1, 4, 6], 
       [8, 5, 9, 6, 8, 0, 0, 1, 3, 0], 
       [3, 2, 8, 9, 5, 8, 6, 5, 6, 7], 
       [6, 7, 5, 1, 1, 0, 5, 1, 9, 0], 
       [8, 9, 4, 5, 9, 7, 0, 0, 0, 4], 
       [7, 9, 6, 7, 4, 7, 5, 1, 7, 4], 
       [6, 8, 2, 6, 1, 9, 8, 5, 2, 1], 
       [9, 1, 1, 3, 7, 6, 8, 0, 8, 7], 
       [2, 8, 6, 3, 6, 5, 0, 3, 1, 8]]) 

N = len(arr) 

def sum_layer(arr, M, N=N): 
    """Function to return the sum of a layer.""" 
    return arr[M:N-M, M:N-M].sum() 

# Each of the layers. 
layers = [sum_layer(arr, i) for i in range(N - N//2)] 

# Subtract the smaller areas from the larger, to get the margins. 
result = [layers[i] - layers[i+1] for i in range(N//2 - 1)] 

# Need to add the final, smallest layer on. 
result.append(layers[-1]) 

print(result) 
# [170, 122, 85, 62, 17] 
7

我想補充另一種答案......雖然來自外部的內減去平方的總體思路可能是最好的辦法,如果你想提出會做太好的實現的性能沒有好,因爲他們不斷增加一遍又一遍的相同數字。爲了加快這個計算了,你可以用圖像處理所謂的積分圖像:

>>> int_arr = np.cumsum(np.cumsum(arr, axis=0), axis=1) 
>>> int_arr 
array([[ 8, 8, 15, 19, 22, 22, 22, 29, 35, 44], 
     [ 16, 17, 24, 34, 40, 44, 46, 54, 64, 79], 
     [ 24, 30, 46, 62, 76, 80, 82, 91, 104, 119], 
     [ 27, 35, 59, 84, 103, 115, 123, 137, 156, 178], 
     [ 33, 48, 77, 103, 123, 135, 148, 163, 191, 213], 
     [ 41, 65, 98, 129, 158, 177, 190, 205, 233, 259], 
     [ 48, 81, 120, 158, 191, 217, 235, 251, 286, 316], 
     [ 54, 95, 136, 180, 214, 249, 275, 296, 333, 364], 
     [ 63, 105, 147, 194, 235, 276, 310, 331, 376, 414], 
     [ 65, 115, 163, 213, 260, 306, 340, 364, 410, 456]]) 

從這個幫手陣列就可以計算任意矩形子陣的添加兩個條目,再減去兩個人的區域,例如:

>>> np.sum(arr[1:-1, 1:-1]) 
286 
>>> int_arr[-2,-2] + int_arr[0, 0] - int_arr[-2, 0] - int_arr[0, -2] 
286 

有了這個,你可以很容易地爲計算你的款項,如:

sums = [int_arr[-1, -1]] 
top = 0 
bot = len(arr) - 2 
while top < bot: 
    new_sum = (int_arr[bot, bot] + int_arr[top, top] - 
       int_arr[top, bot] - int_arr[bot, top]) 
    sums[-1] -= new_sum 
    sums.append(new_sum) 
    top += 1 
    bot -= 1 

>>> sums 
[170, 122, 85, 62, 17] 
相關問題