0
votes

Déterminer les voisins de la cellule en forme de diamant en python

J'ai une variable de matrice de taille où 1 indique la cellule telle que:

Mask    = [[0,0,1,0,0],
           [0,1,1,1,0],
           [1,1,0,1,1],
           [0,1,1,1,0],
           [0,0,1,0,0],
          ]

J'ai besoin de trouver des voisins en forme de diamant de taille paramétrique. Pas une boîte comme réponse donnée ici ou pas un diamant de taille fixe 1, réponse donnée ici . Par exemple, N = 2 Je veux connaître la colonne, les lignes ci-dessous:

Cells   = [[0,0,0,0,0],
           [0,0,0,0,0],
           [0,0,1,0,0],
           [0,0,0,0,0],
           [0,0,0,0,0],
          ]

La fonction doit recevoir x et y pour la colonne et la ligne demandées, (pour ci-dessus, je vais entrer 2,2) et N (entrée 2) la taille du diamant. La fonction doit renvoyer une liste de tuples (x, y) pour la taille de diamant donnée.

J'ai eu du mal à définir la forme en fonction de x, y et k dans des boucles for. J'ai besoin de connaître à la fois une solution numpy (s'il y a quelque chose qui aide) et une solution non numpy.


2 commentaires

Veuillez répéter sur le sujet et comment demander à partir de la visite d'introduction . «Montrez-moi comment résoudre ce problème de codage» n'est pas un problème de débordement de pile. Nous attendons de vous que vous fassiez une tentative honnête, puis que vous posiez une question spécifique sur votre algorithme ou votre technique. Stack Overflow n'est pas destiné à remplacer la documentation et les didacticiels existants. En particulier, nous demander de fournir un code fini sous deux formes est hors de portée; ce n'est pas un service de codage.


Ce n'est qu'une petite partie de ce que j'essaie de réaliser. J'essayais d'être précis mais précis. J'ai fait une tentative et j'ai écrit sur les endroits où j'ai lutté. Pardon.


3 Réponses :


2
votes

Pour une approche itérative où vous construisez simplement le diamant:

dirs = [(1, 0), (0, 1), (-1, 0), (0, -1)]

def add_tuples(a, b):
    return tuple([x + y for (x, y) in zip(a, b)])

def get_neighbors(center, n=1, seen=set()):
    seen.add(center)
    if n <= 0:
        return seen
    for dir in dirs:
        newpos = add_tuples(center, dir)
        if newpos in seen:
            continue
        get_neighbors(newpos, n - 1, seen)
    return seen

Résultat de get_neighbors((2, 2), 2) :

[(0, 2), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (4, 2)]

Ou, pour une approche récursive:

def get_neighbors(center, n=1):
    ret = []
    for dx in range(-n, n + 1):
        ydiff = n - abs(dx)
        for dy in range(-ydiff, ydiff + 1):
            ret.append((center[0] + dx, center[1] + dy))
    return ret


1 commentaires

l'utilisation d'abs est une manière élégante de résoudre ce problème. Probablement cette question recherchait ceci. J'ajouterai cette réponse.



0
votes

Je commencerais par prendre une "sous-matrice" qui est le plus petit carré pouvant contenir vos cellules de résultat. C'est la partie sur laquelle numpy devrait pouvoir vous aider.

Définissez ensuite une fonction qui calcule la distance de Manhattan entre deux cellules (abs (x - x_p) + abs (y - y_p)) et parcourez les cellules de votre sous-matrice et renvoyez les valeurs avec une distance de Manhattan de moins de N à partir de votre origine.


0 commentaires

0
votes
  • Faire un masque avec rotation
  • Cellule et masque convolute
  • Fixez le résultat
  • Filtre diamant Avant la convolution Après convolution et correction

    import numpy as np
    from scipy.ndimage import rotate, convolve
    import matplotlib.pyplot as plt
    
    
    def diamond_filter(radius):
        s = radius * 2 + 1
        x = np.ones((s, s), dtype=int)
        x[radius, radius] = 0
        return rotate(x, angle=45)
    
    
    def make_diamonds(x, radius):
        filter = diamond_filter(radius)
        out = convolve(x, filter)
        out[out > 1] = 1
        out -= x
        out[out < 0] = 0
        return out
    
    
    def plot(x):
        plt.imshow(x)
        plt.show()
        plt.close()
    
    
    def main():
        cell = np.random.choice([0, 1], size=(200, 200), p=[0.95, 0.05])
        plot(diamond_filter(2))
        plot(cell)
        result = make_diamonds(cell, 2)
        plot(result)
    
    
    if __name__ == '__main__':
        main()
    
    
    

0 commentaires