MAC2166 - Introdução à Computação

09/05/2017 - Aula 13

Problema 13.1

Compute a matriz de campo minado (minesweeper)

a) Escreva uma função que recebe como parâmetros uma matriz inteira Anxm, e uma posição (i,j) da matriz, e conta quantas posições ao redor da posição (i,j) contém o valor -1.

b) Escreva um programa que lê uma matriz Anxm de 0's (posições livres) e -1's (minas). Utilizando a função do item anterior, o programa deve computar e imprimir a quantidade de minas ao redor de cada posição livre da matriz.

Exemplo

Para a matriz

00000
0-1-1-10
00000
00-100

a saída deve ser:

12321
1-1-1-11
13431
01-110

Solução 1 (com vários ifs na função conta_minas())

In [1]:
def main():
    m = int(input("Digite o número de linhas da matriz A: "))
    n = int(input("Digite o número de colunas da matriz A: "))
    A = le_matriz(m,n)

    print("Matriz lida:")
    imprime_matriz(A)

    for i in range(m):
        for j in range(n):
            if A[i][j] == 0:
                A[i][j] = conta_minas(A,i,j)
                
    print("Matriz de resultado:")
    imprime_matriz(A)   

def conta_minas(matriz, i, j):
    """
    (list, int, int) --> int
    Função que recebe como parâmetro uma matriz e uma posição (i,j)
    dessa matriz e devolve a quantidade de posições ao redor da posição
    (i,j) que contêm o valor -1 nessa matriz.

    """
    cont = 0
    
    # Verifica a posição à esquerda
    if j-1 >= 0 and matriz[i][j-1] == -1:
        cont +=1

    # Verifica a posição à direita
    if j+1 < len(matriz[i]) and matriz[i][j+1] == -1:
        cont +=1

    # Verifica as posições acima
    if i-1 >= 0:
        if matriz[i-1][j] == -1:
            cont +=1
        if j-1 >= 0 and matriz[i-1][j-1] == -1:
            cont +=1
        if j+1 < len(matriz[i]) and matriz[i-1][j+1] == -1:
            cont +=1

    # Verifica as posições abaixo
    if i+1 < len(matriz):
        if matriz[i+1][j] == -1:
            cont +=1
        if j-1 >= 0 and matriz[i+1][j-1] == -1:
            cont +=1
        if j+1 < len(matriz[i]) and matriz[i+1][j+1] == -1:
            cont +=1
    
    return cont

def le_matriz(m, n):
    """
    (int, int) --> list
    
    Função que recebe como entrada um número de linhas m
    e um número de colunas n e então lê uma matriz de inteiros
    tamanho m x n, ou seja, uma lista contendo m listas
    com n elementos cada. A matriz lida é devolvida como
    valor de retorno da função. 
    """

    print("Digite os elementos da matriz de tamanho %dx%d:" %(m,n))
    matriz = []
    for i in range(m):
        matriz.append([])
        for j in range(n):
            elemento = int(input("Elemento da %da. linha, %da. coluna: " %(i+1,j+1)))
            matriz[i].append(elemento)
            
    return matriz

def imprime_matriz(matriz):
    """
    (list) --> None

    Função que recebe uma matriz como entrada, ou seja uma
    lista de listas, e então a imprime.
    A função não tem nenhum valor de retorno.
    """
    
    for linha in matriz:
        for elemento in linha:
            print("%2d" %elemento, end = " ")
        print()

 
################
main()
Digite o número de linhas da matriz A: 4
Digite o número de colunas da matriz A: 5
Digite os elementos da matriz de tamanho 4x5:
Elemento da 1a. linha, 1a. coluna: 0
Elemento da 1a. linha, 2a. coluna: 0
Elemento da 1a. linha, 3a. coluna: 0
Elemento da 1a. linha, 4a. coluna: 0
Elemento da 1a. linha, 5a. coluna: 0
Elemento da 2a. linha, 1a. coluna: 0
Elemento da 2a. linha, 2a. coluna: -1
Elemento da 2a. linha, 3a. coluna: -1
Elemento da 2a. linha, 4a. coluna: -1
Elemento da 2a. linha, 5a. coluna: 0
Elemento da 3a. linha, 1a. coluna: 0
Elemento da 3a. linha, 2a. coluna: 0
Elemento da 3a. linha, 3a. coluna: 0
Elemento da 3a. linha, 4a. coluna: 0
Elemento da 3a. linha, 5a. coluna: 0
Elemento da 4a. linha, 1a. coluna: 0
Elemento da 4a. linha, 2a. coluna: 0
Elemento da 4a. linha, 3a. coluna: -1
Elemento da 4a. linha, 4a. coluna: 0
Elemento da 4a. linha, 5a. coluna: 0
Matriz lida:
 0  0  0  0  0 
 0 -1 -1 -1  0 
 0  0  0  0  0 
 0  0 -1  0  0 
Matriz de resultado:
 1  2  3  2  1 
 1 -1 -1 -1  1 
 1  3  4  3  1 
 0  1 -1  1  0 

Solução 2 (implementação mais "enxuta" da função conta_minas())

In [8]:
def main():
    m = int(input("Digite o número de linhas da matriz A: "))
    n = int(input("Digite o número de colunas da matriz A: "))
    A = le_matriz(m,n)

    print("Matriz lida:")
    imprime_matriz(A)

    for i in range(m):
        for j in range(n):
            if A[i][j] == 0:
                A[i][j] = conta_minas(A,i,j)
                
    print("Matriz de resultado:")
    imprime_matriz(A)   
    

def conta_minas(matriz, i, j):
    """
    (list, int, int) --> int
    Função que recebe como parâmetro uma matriz e uma posição (i,j)
    dessa matriz e devolve a quantidade de posições ao redor da posição
    (i,j) que contêm o valor -1 nessa matriz.

    """
    cont = 0
    
    for incremento_linha in [-1, 0, 1]:  # queremos olhar para as linhas i-1, i e i+1
        for incremento_coluna in [-1, 0, 1]:  # queremos olhar para as colunas j-1, j e j+1
            
            # se a posição matriz[i+incremento_linha][j+incremento_coluna] é válida e não é a própria matriz[i][j],
            # verifica se ela contém uma mina
            if (0 <= i+incremento_linha < len(matriz) and 0 <= j+incremento_coluna < len(matriz[i]) and # posição é válida?
                    not (incremento_linha == 0 and incremento_coluna == 0) and   # a posição não é a própria (i,j)?
                    matriz[i+incremento_linha][j+incremento_coluna] == -1):      # tem mina?
                cont += 1
    
    return cont



def le_matriz(m, n):
    """
    (int, int) --> list
    
    Função que recebe como entrada um número de linhas m
    e um número de colunas n e então lê uma matriz de inteiros
    tamanho m x n, ou seja, uma lista contendo m listas
    com n elementos cada. A matriz lida é devolvida como
    valor de retorno da função. 
    """

    print("Digite os elementos da matriz de tamanho %dx%d:" %(m,n))
    matriz = []
    for i in range(m):
        matriz.append([])
        for j in range(n):
            elemento = int(input("Elemento da %da. linha, %da. coluna: " %(i+1,j+1)))
            matriz[i].append(elemento)
            
    return matriz

def imprime_matriz(matriz):
    """
    (list) --> None

    Função que recebe uma matriz como entrada, ou seja uma
    lista de listas, e então a imprime.
    A função não tem nenhum valor de retorno.
    """
    
    for linha in matriz:
        for elemento in linha:
            print("%2d" %elemento, end = " ")
        print()

 
################
main()
Digite o número de linhas da matriz A: 4
Digite o número de colunas da matriz A: 5
Digite os elementos da matriz de tamanho 4x5:
Elemento da 1a. linha, 1a. coluna: 0
Elemento da 1a. linha, 2a. coluna: 0
Elemento da 1a. linha, 3a. coluna: 0
Elemento da 1a. linha, 4a. coluna: 0
Elemento da 1a. linha, 5a. coluna: 0
Elemento da 2a. linha, 1a. coluna: 0
Elemento da 2a. linha, 2a. coluna: -1
Elemento da 2a. linha, 3a. coluna: -1
Elemento da 2a. linha, 4a. coluna: -1
Elemento da 2a. linha, 5a. coluna: 0
Elemento da 3a. linha, 1a. coluna: 0
Elemento da 3a. linha, 2a. coluna: 0
Elemento da 3a. linha, 3a. coluna: 0
Elemento da 3a. linha, 4a. coluna: 0
Elemento da 3a. linha, 5a. coluna: 0
Elemento da 4a. linha, 1a. coluna: 0
Elemento da 4a. linha, 2a. coluna: 0
Elemento da 4a. linha, 3a. coluna: -1
Elemento da 4a. linha, 4a. coluna: 0
Elemento da 4a. linha, 5a. coluna: 0
Matriz lida:
 0  0  0  0  0 
 0 -1 -1 -1  0 
 0  0  0  0  0 
 0  0 -1  0  0 
Matriz de resultado:
 1  2  3  2  1 
 1 -1 -1 -1  1 
 1  3  4  3  1 
 0  1 -1  1  0 

Problema 13.2

a) Escreva uma função que recebe como parâmetros uma matriz real Anxm, e uma posição (i,j) da matriz, e calcula a média aritmética dos vizinhos de (i,j), ou seja, a média entre A[i-1][j], A[i+1][j], A[i][j-1] e A[i][j+1]. Desconsidere os vizinhos que não pertencem a matriz (por exemplo, os vizinhos de (0,0) são somente (0,1) e (1,0)).

b) Escreva uma função que recebe como parâmetro uma matriz real Anxm e devolve uma matriz Amédia, onde Amédia[i][j] é a média aritmética dos vizinhos de (i,j). Para isto, utilize a função do item anterior.

c) Escreva um programa que lê uma matriz real Anxm, e um número inteiro k; utilizando a função do item anterior, o programa deve transformar a matriz k vezes, imprimindo a matriz inicial e depois de cada transformação.

Obs.: Este problema corresponde ao exercício 13 da lista de exercícios sobre funções - Parte III.

Solução

In [13]:
def main():
    m = int(input("Digite o número de linhas da matriz A: "))
    n = int(input("Digite o número de colunas da matriz A: "))
    A = le_matriz(m,n)
    k = int(input("Digite o numero k de transformacoes em A:"))

    print("Matriz lida:")
    imprime_matriz(A)

    for i in range(k):
        A = matriz_media(A)        
        print("Matriz de resultado (transformaçao %d):" %(i+1))
        imprime_matriz(A)
    
def media_vizinhos(A,i,j):
    """
    (list,int,int) --> float
    Função que recebe uma matriz e um posição (i,j) desta matriz e
    devolve a média dos valores das posições ao redor de (i,j).
    """
    cont = 0
    soma = 0
    # Soma o valor da posição à esquerda
    if j-1 >= 0:
        cont +=1
        soma += A[i][j-1]

    # Soma o valor da posição à direita
    if j+1 < len(A[i]):
        cont +=1
        soma += A[i][j+1]

    # Soma o valor da posição acima
    if i-1 >= 0:
        cont +=1
        soma += A[i-1][j]

    # Soma o valor da posição abaixo
    if i+1 < len(A):
        cont +=1
        soma += A[i+1][j]
    
    return soma/cont

def matriz_media(A):
    """
    (list) --> list
    Função que recebe uma matriz A de reais e devolve uma nova matriz
    onde cada posição (i,j) possui o valor da média dos valores dos
    vizinhos da posição (i,j) em A.
    """
    A_media = []
    for i in range(len(A)):
        A_media.append([])
        for j in range(len(A[i])):
            A_media[i].append(media_vizinhos(A,i,j))
    return A_media


def le_matriz(m, n):
    """
    (int, int) --> list
    
    Função que recebe como entrada um número de linhas m
    e um número de colunas n e então lê uma matriz de reais
    tamanho m x n, ou seja, uma lista contendo m listas
    com n elementos cada. A matriz lida é devolvida como
    valor de retorno da função. 
    """

    print("Digite os elementos da matriz de tamanho %dx%d:" %(m,n))
    matriz = []
    for i in range(m):
        matriz.append([])
        for j in range(n):
            elemento = float(input("Elemento da %da. linha, %da. coluna: " %(i+1,j+1)))
            matriz[i].append(elemento)
            
    return matriz

def imprime_matriz(matriz):
    """
    (list) --> None

    Função que recebe uma matriz real como entrada, ou seja uma
    lista de listas, e então a imprime.
    A função não tem nenhum valor de retorno.
    """
    
    for linha in matriz:
        for elemento in linha:
            print("%6.2f" %elemento, end = " ")
        print()

##########
main()
Digite o número de linhas da matriz A: 3
Digite o número de colunas da matriz A: 2
Digite os elementos da matriz de tamanho 3x2:
Elemento da 1a. linha, 1a. coluna: 34.9
Elemento da 1a. linha, 2a. coluna: 178.9
Elemento da 2a. linha, 1a. coluna: 21.43
Elemento da 2a. linha, 2a. coluna: 0.172
Elemento da 3a. linha, 1a. coluna: 87.21
Elemento da 3a. linha, 2a. coluna: 0.789
Digite o numero k de transformacoes em A:4
Matriz lida:
 34.90 178.90 
 21.43   0.17 
 87.21   0.79 
Matriz de resultado (transformaçao 1):
100.17  17.54 
 40.76  67.04 
 11.11  43.69 
Matriz de resultado (transformaçao 2):
 29.15  83.60 
 59.44  34.00 
 42.23  39.07 
Matriz de resultado (transformaçao 3):
 71.52  31.57 
 35.12  60.70 
 49.26  38.11 
Matriz de resultado (transformaçao 4):
 33.35  66.11 
 60.49  34.94 
 36.62  54.98 

Tópicos vistos na Aula 13

  • Mais funções que recebem matrizes como parâmetro e/ou que devolvem matrizes