Home > OS >  making a diamond of 0 in a 1's matrix - numpy
making a diamond of 0 in a 1's matrix - numpy

Time:06-18

so the assignment is: write a func that gets N ( int greater than 0 ) and return a 2d array of 1's where a path of 0 makes a diamond. the length of each diamond line(1 of 4 lines) is of length N. cannot use loops list comps or recursion.

i will add my own solution but I don't think it is very numpy oriented.. please note that my solution was originally for a diamond of 1's in a 0 matrix so it might look a bit odd

example: n=1

np.array([[0]])

n=2:

np.array([[1,0,1],[0,1,0],[1,0,1]])

n=3

np.array([[1,1,0,1,1],[1,0,1,0,1],[0,1,1,1,0],[1,0,1,0,1],[1,1,0,1,1]])

My Solution:

    if n == 1:
        finalMatrix = np.array([[0]])
        return finalMatrix
    rawMatrix = np.ones((2 * n - 1, 2 * n - 1))
    midRowDiag = np.eye(2 * n - 1, k=n - 1)
    midColDiag = np.eye(2 * n - 1, k=-(n - 1))
    tempMatrix = rawMatrix - midRowDiag - midColDiag
    halfMatrix = tempMatrix[::, n:]
    # print(halfMatrix)

    # Making the quarters
    topRightQuart = halfMatrix[:n - 1, 0:n - 1]
    topLeftQuart = np.fliplr(topRightQuart)
    botLeftQuart = np.flipud(topLeftQuart)
    botRightQuart = np.flipud(topRightQuart)
    midCol = tempMatrix[:, n - 1]
    midRow = tempMatrix[n - 1, :]
    # Adding them all up
    finalMatrix = np.zeros((2 * n - 1, 2 * n - 1))
    finalMatrix[:, n - 1]  = midCol
    finalMatrix[n - 1, :]  = midRow
    finalMatrix[0:n - 1, 0:n - 1]  = topLeftQuart
    finalMatrix[0:n - 1, n:]  = topRightQuart
    finalMatrix[n:, 0:n - 1]  = botLeftQuart
    finalMatrix[n:, n:]  = botRightQuart
    finalMatrix[n - 1, n - 1] = 1
    return finalMatrix

CodePudding user response:

arr = np.diagflat([1,1],1)
arr = np.maximum(arr,np.flip(arr,0))
arr = np.maximum(arr,np.flip(arr,1))  
arr = np.where((arr==0)|(arr==1), arr^1, arr)

As per my understanding you are looking to make diamonds write. This is an example for 3x3 one for 5x5 the code is underneath

arr = np.diagflat([1,1,1],2)
arr = np.maximum(arr,np.flip(arr,0))
arr = np.maximum(arr,np.flip(arr,1))  
arr = np.where((arr==0)|(arr==1), arr^1, arr)

so for n needs to be a odd number and n=odd number list of 1 len = n//2 1 and the second parameter in np.diagflat will be n//2. This is important to use // or you can simply divide and round it off

if n is the length of diagonal then the second parameter will be n-1

CodePudding user response:

This pattern looks similar to a Toeplitz matrix. You can implement this using scipy.linalg.toeplitz:

>>> p = np.array([1,1,0,1,1])
>>> T = toeplitz(p, p)

Notice the layout of T:

array([[1, 1, 0, 1, 1],
       [1, 1, 1, 0, 1],
       [0, 1, 1, 1, 0],
       [1, 0, 1, 1, 1],
       [1, 1, 0, 1, 1]])

We can horizontally flip it (np.fliplr) and point-wise multiply with itself:

 >>> T*np.fliplr(T)
array([[1, 1, 0, 1, 1],
       [1, 0, 1, 0, 1],
       [0, 1, 1, 1, 0],
       [1, 0, 1, 0, 1],
       [1, 1, 0, 1, 1]])

Minimal implementation:

def diamond(n):
    pad = (1,)*(n-1)
    p = np.array(pad   (0,)   pad)
    T = toeplitz(p, p)
    return np.fliplr(T)*T

Then:

>>> diamond(1)
array([[0]])

>>> diamond(2)
array([[1, 0, 1],
       [0, 1, 0],
       [1, 0, 1]])

>>> diamond(3)
array([[1, 1, 0, 1, 1],
       [1, 0, 1, 0, 1],
       [0, 1, 1, 1, 0],
       [1, 0, 1, 0, 1],
       [1, 1, 0, 1, 1]])
  • Related