2014-12-24 21 views

Antwort

2

Hier ist eine Lösung ohne wiederholte Summierung aus den gleichen Elementen und mit aus einem Zwischenfeld (nur Brute-Force-Indizierung Spaß), die für quadratische n von n Arrays für ungerade arbeitet oder sogar 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)) 

Produziert:

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

Sie schaffen tatsächlich viele kleine Zwischen-Arrays ... Wenn Sie tun, z.'sum (a [i, i: n-i] + a [n-i-1, i: n-i])', numpy weist ein neues 'n-2 * i'-Element-Array zu und füllt es mit der elementweisen Summe der beiden Slices. Dies ist natürlich leicht zu vermeiden, mit einer wahrscheinlich nicht zu vernachlässigenden Geschwindigkeit, indem jede Scheibe einzeln summiert wird, bevor sie zusammengefügt werden. Sie sollten auch "np.sum" anstelle der "Summe" der Standardbibliothek verwenden. – Jaime

+0

@Jaime - du hast natürlich Recht: Ich war hier ein bisschen sorglos. Ich habe den vorgeschlagenen Code bearbeitet. Vielen Dank. – xnx

0

Ich habe eine Idee. 1. Finden Sie die Summe der gesamten 10 * 10-Array, dann finden Sie die Summe der inneren 9 * 9-Array. Dann ist die Subtraktion das Ergebnis der Summe der äußeren Schicht.

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

Eine Schleife wird alle Summe finden.

werden kann, gibt es eine bessere Art und Weise, dies zu tun ..

2

Wenn Sie wissen, wie die Summe eines (2n)*(2n) Quadrat in der Mitte zu bekommen, dann ist es sehr einfach: Nehmen Sie die Summe des (2n)*(2n) Platz, dann subtrahiere die Summe des (2n-2)*(2n-2) Quadrats darin; die Differenz ist die Summe der Elemente auf der Grenze (das heißt, in dem äußeren Quadrat aber nicht die innere):

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

Der folgende Code berechnet jede Schicht und subtrahiert dann die kleinere Schicht davon. Es ist ziemlich allgemein, und so sollte jedes Array der Größe N * N an es übergeben werden können, solange N sogar ist (denke ich).

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

einfach eine andere Antwort hinzufügen ... Während die allgemeine Idee der Subtraktion inneren Quadrate aus Äußeren ist wahrscheinlich der beste Ansatz, wenn Sie die Leistung keine der Implementierungen wollte täte präsentiert zu gut, da sie das Hinzufügen halten immer wieder dieselben Zahlen. Um diese Berechnung bis zu beschleunigen, können Sie, was in der Bildverarbeitung verwenden ist ein integrales Bild genannt:

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

Von diesem Helfer Array können Sie den Bereich eines rechteckigen Subarray berechnen Hinzufügen von zwei Einträgen und Subtrahieren zwei andere, zB:

>>> 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 

Damit könnten Sie Ihre Summen leicht wie zB berechnen:

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] 
Verwandte Themen