0

I have an numpy array that looks like this

[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]

Now I have an 2d array that tells the start index and the end index and the value to sum. like this

[[5, 12, 29] [8, 22, 719]]

I want to add these numbers to my initial array faster.

Currently my solution is

f= np.zeros(n+1, dtype = int)

# print(rounds)
for elem in rounds:
    print('rounds : ',elem)
    one = elem[0]
    two = elem[1]
    value_add = elem[2]
# for i in range(0,n+1):
    for i in range(one-1,two):
        f[i-1] += value_add
        # print(f)

Its very slow when matrix gets too long, Any other way to optimize ?

2nd Iteration try for optimization

import numpy as np

f= np.zeros(n+1, dtype = int)

# print(rounds)
new = np.zeros(n+1)
for elem in rounds:
    # prin  t('rounds : ',elem)
    one = elem[0]
    two = elem[1]
    value_add = elem[2]
# for i in range(0,n+1):

    new[one-1:two] += value_add
2
  • I'm not entirely clear about the 'summing' part. Am I right in assuming that the elements of the original array must be increased by a certain amount, starting at the first index and ending just before the second one? That is to say, an entry like [2, 5, 3] would result in the original changing to [1, 2, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]? Commented Feb 29, 2020 at 15:12
  • yes, thats correct Commented Feb 29, 2020 at 15:16

2 Answers 2

1

You could create masks and use indirection to let numpy do all the work (i.e without any loops):

import numpy as np
a   = np.array([1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2])
iv  = np.array([[5, 12, 29], [8, 22, 719]])

valueMask     = (np.arange(a.size)>=iv[:,0:1]) & (np.arange(a.size)<iv[:,1:2])
valueIndex    = np.max((np.arange(iv.shape[0])+1)[:,None]*valueMask,axis=0)-1
targetMask    = valueIndex>=0
a[targetMask] = iv[valueIndex[targetMask],2]

output:

print(a)

[  1   2   2   2   2  29  29  29 719 719 719 719 719 719 719 719 719 719  719]

The valueMask variable is a true/false matrix of positions in a where each value of iv would be assigned.

The valueIndex variable converts the masks into a 1D array indicating which of the iv value (index) will be assigned last at each position. It will contain -1 for positions that are not changed.

The targetMask variable picks out the positions of a that will actually receive a new value and excludes the positions that will not be changed. It results in a true/false mask of positions to use in the indirection for value assignment.

The last step is to assign the subset of elements in a defined by targetMask with the corresponding values of iv using the last value (highest index of iv) that would be assigned.

I hope this will give you the performance you need. I measured assigning 300 ranges to a 2000 item array and got a time of 0.0028 seconds on my laptop.

Sign up to request clarification or add additional context in comments.

Comments

0

How about this?

a = np.array([1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2])
instr_array = np.array([[5, 12, 29], [8, 22, 719]])

for start, end, incr in instr_array:
    a[start:end] += incr

3 Comments

yeah and I still getting time penalty for 8 out of 14 test cases.
Where are these tests hosted, if I may ask?
On hackerrank plateform.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.