quinta-feira, 10 de dezembro de 2009

Matrizes, ciclos imbricados e impressões

Todos estamos habituados a lidar com informação cujo acesso se faz por indicação das suas coordenadas num espaço a n dimensões. Por exemplo, quando lidados com imagens, cada pixel é referenciado dessa forma, por duas coordenadas. Os matemáticos arranjaram um modo de organizar essa informação através de matrizes. Os cálculos complexos que temos que fazer com matrizes podem ser facilmente passados para o computador. Como aqui já referimos, a linguagem Python tem módulos que permitem lidar com matrizes (Scipy, por exemplo). Mas vamos supor que tal não existe. Um modo natural de representar uma matriz seria por recurso a uma lista de listas. Cada lista interior representa uma linha da matriz. Por exemplo:


matriz = [[1,2,3],[4,5,6],[7,8,9]]

Vamos ver como podemos visualizar os elementos de uma matriz quadrada qualquer. A questão essencial que temos que ter em conta é que, havendo duas dimensões, temos que criar dois ciclos, um dentro do outro,em que cada um deles responsável por percorrer de modo ordenado cada uma das dimensões. Vejamos o caso mais simples, ou seja, mostrar todos os elementos.

def mostra_por_linhas(matriz):
“””Indexação pelo conteúdo.”””
for linha in matriz:
for coluna in linha:
print “%3d” % coluna,
print


def mostra_por_linhas(matriz):
“””Indexação pela posição.”””
for pos_linha in range(len(matriz)):
for pos_coluna in range(len(matriz[0])):
print “%3d” % matriz[pos_linha][pos_coluna],
print

O que têm estes dois programas de diferente? O simples facto de, no primeiro, percorremos a matriz usando o seu conteúdo, enquanto que, no segundo, usamos as posições. E de comum, que pontos devem ser salientados??? Essencialmente o modo como fazemos a impressão: o comando print usa uma marca de formatação (%3d) e termina com uma vírgula. É este último facto que permite colocar os elementos de uma linha todos ao lado uns dos outros. O segundo print sem argumento serve apenas para mudar de linha.

Admitamos agora que queremos mostrar a matriz por colunas e não por linhas.

def mostra_por_colunas(matriz):
""" AKO transposta. Indexação pelo conteúdo."""
for pos_coluna in range(len(matriz[0])):
for pos_linha in range(len(matriz)):
print "%3d" % matriz[pos_linha][pos_coluna],
print

Bastou trocar a ordem: o primeiro ciclo trata das colunas, enquanto o segundo ciclo (mais interior) as linhas!

E se forem as matrizes triangulares superior e inferior??

def mostra_tri_sup(matriz):
"""Matriz triangular superior.Indexação pela posição."""
for pos_linha in range(len(matriz)):
print ' '* 3 * pos_linha, # 3 por causa do %2d
for pos_coluna in range(pos_linha,len(matriz[0])):
print "%2d" % matriz[pos_linha][pos_coluna],
print

def mostra_tri_inf(matriz):
"""Matriz triangular superior.Indexação pela posição."""
for pos_linha in range(len(matriz)):
for pos_coluna in range(0,pos_linha+1):
print "%2d" % matriz[pos_linha][pos_coluna],
print

Atente-se como tratamos de mostrar de modo conveniente. uma vez mais o comando print é essencial para esse objectivo. Terminamos com a matriz diagonal.

def mostra_diag_principal(matriz):
""" Mostra diagonal principal."""
for pos_linha in range(len(matriz)):
print ' '* 3 * pos_linha,
for pos_coluna in range(0,pos_linha+1):
if pos_linha == pos_coluna:
print "%2d" % matriz[pos_linha][pos_coluna]

Deixamos ao leitor a tarefa de testar estes programas. Fica também como exercício resolver o problema não de visualizar mas de criar.

Sem comentários:

Enviar um comentário