Munchkin
Munchkin

Reputation: 4946

Efficient algorithm for matrix calculation

In addition to this efficient algorithm for list edits I'm looking for a more efficient algorithmus for another "loop calculation". This time I have a matrix like:

grid_z1 = [[1,2,3],
           [4,5,6],
           [7,8,9]]

and the user can enter several parameters: goal is, to change the values inside the matrix into the parameter-value which is the next highest (and if a matrix-value is higher than max(paramter) than change it to nan) for example, when the user entered a "4" and a "7", then the matrix-value "5" shall change to "7" (=next highest of the entered values). example:

h = [2, 7, 4] # user entered this three values
grid_z1 = [[2, 2, 4],
           [4, 7, 7],
           [7, nan, nan]] # this should be my output

In addition I want to count the number of values which changed into the given values. in my example this should be [2,2,3] -> 2x2, 2x4, 3x7

h.sort()
h.reverse()

count = [0]*len(h)

for i in range(len(grid_z1)):
    for j in range(len(grid_z1[0])):
        if grid_z1[i][j] > max(h):
            grid_z1[i][j] = float('NaN')
        else:
            for k in range(len(h)-1):
                if grid_z1[i][j] <= h[k] and grid_z1[i][j] > h[k+1]:
                    grid_z1[i][j] = h[k]
                    count[k] += 1
            if grid_z1[i][j] <= min(h):
                grid_z1[i][j] = min(h)
                count[-1] += 1

print grid_z1
print count

But again it's very slow. Sadly I don't understand the zip-method enough to use it for this more complex algorithmus.

Upvotes: 1

Views: 152

Answers (2)

Jordonias
Jordonias

Reputation: 5848

for i,row in enumerate(g):
        g[i] = [float('nan') if item > max(h) else min([x for x in h if x >= item]) for item in row]

Upvotes: 0

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 250951

Using bisect module:

from bisect import bisect_left
def solve(matrix, param):
    param.sort()             #Sort the params passed by user
    maxx = param[-1]         #Find max
    for row in matrix:
        # If item in the row is greater than `maxx` then use Nan
        # else use bisect_right to get the next highest item from
        # params in O(log N) time.
        yield [float('nan') if item > maxx else
                                 param[bisect_left(param, item)] for item in row]

grid_z1 = [[1,2,3],
           [4,5,6],
           [7,8,9]]
print list(solve(grid_z1, [2, 7, 4]))   

Output:

[[2, 2, 4], [4, 7, 7], [7, nan, nan]]

Upvotes: 2

Related Questions