Find adjacent cells in a matrix

3

I'm having trouble finding and verifying the cells adjacent to a certain position within the matrix (one cell can have 8 adjacent cells). The matrix is composed of a list of chains. So far I have tested the following but it does not exceed assert number 4:

def cant_adyacentes(life, f, c):

"""Calcula la cantidad de células adyacentes a la celda en la fila 'f' y la
columna 'c'."""

   celulas_adyacentes = 0
    for i in range(f-1,f+2):
        for j in range(c-1,c+2):
            if i == len(life) or j == len(life[i]):
                break
            if life[i][j] == "#":
                celulas_adyacentes+=1

    return celulas_adyacentes

In addition, you must comply with the following asserts :

def pruebas_cant_adyacentes():
"""Prueba el correcto funcionamiento de cant_adyacentes()."""
    assert cant_adyacentes((['.']), 0, 0) == 0
    assert cant_adyacentes((['..', '..']), 0, 0) == 0
    assert cant_adyacentes((['..', '..']), 0, 1) == 0
    assert cant_adyacentes((['##', '..']), 0, 0) == 2
    assert cant_adyacentes((['##', '..']), 0, 1) == 2
    assert cant_adyacentes((['#.', '.#']), 0, 0) == 4
    assert cant_adyacentes((['##', '##']), 0, 0) == 8
    assert cant_adyacentes((['.#.', '#.#', '.#.']), 1, 1) == 4
    assert cant_adyacentes((['.#.', '..#', '.#.']), 1, 1) == 3
    
asked by FacuM 14.04.2017 в 03:15
source

1 answer

2

Your code is correct if you want to count the elements adjacent to a given one in a finite matrix. The problem is that your matrix is theoretically infinite.

I do not know if you're limited to doing it using cycles for or anything else. Otherwise, it is very simple if you use slicing of lists / strings and the module operation or rest of the whole division:

  • We have for example the case of the matrix:

    #.
    .#
    

    And they ask us to count the cells adjacent to the element (0,0)

  • What we need is to reconstruct the 3x3 matrix that would result from centering the one we have (which in reality is infinite) in the element that they indicate to us. In our case it would be to obtain the following matrix:

    #.#        
    .#.
    #.#
    
  • To do this we must consider a couple of things:

    • Phyton allows the use of negative indexes:

      >>> s='hola'
      >>> print(s[-1])
      >>> a
      
    • If we want to create a circular or cyclical list we can make use of modular arithmetic using the module operator ( % ) or rest of the whole division:

      def elemento(iterable, indice):
          return(iterable[indice%len(iterable)])
      
      s = 'Hola-'
      for i in range(0,20):
          print(elemento(s, i))
      

We can see how we can pass an index as large as we want and thanks to modular arithmetic we can travel with infinite indexes a finite list. With these two ideas we can iterate infinitely on any iterable in both directions.

  • In reality we only need the 8 peripheral elements of the previous matrix and count those that are '#' . For this we can use the method count .

With the above concepts the code is simply in:

def cant_adyacentes(life, f, c):
    fs = life[f-1]
    fi = life[(f+1)%len(life)]
    i=(c+1)%len(life[0])
    return (fs[c-1], fs[c], fs[i], life[f][c-1], life[f][i], fi[c-1], fi[c], fi[i]).count('#')

def pruebas_cant_adyacentes():
    assert cant_adyacentes((['.']), 0, 0) == 0
    assert cant_adyacentes((['..', '..']), 0, 0) == 0
    assert cant_adyacentes((['..', '..']), 0, 1) == 0
    assert cant_adyacentes((['##', '..']), 0, 0) == 2
    assert cant_adyacentes((['##', '..']), 0, 1) == 2
    assert cant_adyacentes((['#.', '.#']), 0, 0) == 4
    assert cant_adyacentes((['##', '##']), 0, 0) == 8
    assert cant_adyacentes((['.#.', '#.#', '.#.']), 1, 1) == 4
    assert cant_adyacentes((['.#.', '..#', '.#.']), 1, 1) == 3

pruebas_cant_adyacentes()

fs is the row that is above the one that contains the element on which we calculate the adjacent cells.

fi is the bottom row.

i is the index using modular arithmetic that we must use to obtain the elements of the column located to the right of the one that contains our target element.

The elements on the left or the top row do not give problems because Python itself understands the negative indices and at most we will need the -1 index. The elements on the right or rows below if they give problems because if the index is greater than the length of the iterable minus one will generate an error. In this last case we make use of modular arithmetic.

    
answered by 14.04.2017 / 19:28
source