2

I have a problem to solve with a Python code.

  • Input ( M ) = 2D array with integer numbers
  • Output (T ) same 2D array but with 0 and 1.
  • Ti,j = 1 if all the neighbors of the integer Mi,j (in the 8 possible directions) are STRICTLY smaller than the Mi,j.
  • Otherwise, in the opposite case, Ti,j = 0 if there is at least one neighbor in the matrix M greater than or equal to Mij.

I try with this code but it doesn't return the correct T.

def findmaximun(M):
    # Write your code here
    r, c = len(M),len(M[0])
    T = [[1 for col in range(c)] for row in range(r)]
    for i in range(0,r):
        for j in range(0,c): 
            for k in [-1,0,1]:
                if i+k>=0 and i+k<r:
                    for l in [-1,0,1]:
                        if j+l>=0 and j+l<c and max(-i-k,0)!=max(-j-l,0):
                            if M[i][j] <= M[i+k][j+l]:
                                      T[i][j]=0                
    return(T)
Nico Albers
  • 1,556
  • 1
  • 15
  • 32
datascientist
  • 81
  • 1
  • 6
  • Can you give some example input/output? What have you done to try to fix this? I recommend reading the following article: https://ericlippert.com/2014/03/05/how-to-debug-small-programs/. – AMC Jan 18 '20 at 15:42
  • Have a look at the numpy library. The code will be much shorter and easier to understand and change. – eumiro Jan 18 '20 at 16:34
  • how do you define a neighbour in this case? – YOLO Jan 18 '20 at 16:50
  • The problem you are describing is often referred to as finding "local maxima" or "peak detection" and scipy or skimage have off-the-shelf filters to do so. Using numpy is definitely an option as eumiro suggested; instead of looping over every index and every neighbour, you can make 8 matrix to matrix comparisons for "each neighbour in bulk". – Pierre Schroeder Jan 18 '20 at 16:53
  • Thank you guys for your answers. Numpy, scipy or other libraries are actually not allowed to be used in those kind of challenges as in Hackerrank. – datascientist Jan 19 '20 at 16:12

2 Answers2

0
def findmaximun(M):
    # Write your code here
    r, c = len(M), len(M[0])
    T = [[1 for col in range(c)] for row in range(r)]

    #  all neighbors
    ds = [(1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1)]

    for i in range(0, r):
        for j in range(0, c):
            for dx, dy in ds:
                x = i + dx
                y = j + dy
                if (0 <= x < r and 0 <= y < c and M[x][y] >= M[i][j]):
                    T[i][j] = 0
                    break

    return (T)
hongfei
  • 26
  • 2
0

my solution is very explicit. I'm sure there is a more elegant way of handling the edge cases, but it may not be as readable. Ideally one would use numpy for such a task. It's way faster and offers better indexing and array operations. Also instead of typing out idx explicitly, one could use itertools.

I validated the code with matplotlibs imshow

import random

r = 10
c = 15

M = []
for i in range(r):
    M.append([])
    for j in range(c):
        M[i].append(random.random())


def find_max(M):
    # Setup array dimensions and output array
    r, c = len(M), len(M[0])
    T = [[0 for col in range(c)] for row in range(r)]
    # iterate over array
    for i, row in enumerate(M):
        for j, elem in enumerate(row):
            # handle edge cases (literally!)
            if i == 0:
                if j==0:
                    idx = [(1,0), (1,1), (0,1)]
                elif j==c-1:
                    idx = [(1,0), (1,-1), (0,-1)]
                else:
                    idx = [(1,0), (1,1), (0,1), (1,-1), (0,-1)]
            elif i==r-1:
                if j==0:
                    idx = [(-1,0), (-1,1), (0,1)]
                elif j==c-1:
                    idx = [(-1,0), (-1,-1), (0,-1)]
                else:
                    idx = [(-1,0), (-1,1), (0,1), (-1,-1), (0,-1)]
            else:
                if j==0:
                    idx = [(-1,0), (-1,1), (0,1), (1,1), (1,0)]
                elif j==c-1:
                    idx = [(-1,0), (-1,-1), (0,-1), (1,-1), (1,0)]
                else:
                    idx = [(0,1), (1,1), (1,0), (1,-1), (0,-1), (-1,-1), (-1,0), (-1,1)]
            # get the neighbors
            neighbors = []
            for x, y in idx:
                neighbors.append(M[i + x][j + y])
            # calculate t    
            if elem > max(neighbors):
                T[i][j] = 1
    return T
T = find_max(M)

AlexNe
  • 926
  • 6
  • 22