sábado, 2 de outubro de 2010

Problema 1.6

Os problemas da Ficha 1 são todos muito acessíveis. Não deixam por vezes de nos ensinar algumas coisas. Uma é que devemos testar sempre o programa na tentativa de eliminar a possibilidade de erros. Os testes devem ser feitos usando exemplos que explorem casos típicos e limites. Vamos exemplificar com o problema 1.6. Recordemos o enunciado.

Imagine uma lista telefónica em que cada página tem L linhas e cada linha C colunas. Em cada posição (Linha,Coluna) é guardada a informação pertinente. Admita que as páginas, linhas e colunas se iniciam sempre a 1. Conhecido o índice da sua informação, em que página, linha e coluna se encontra?

Trata-se de um problema semelhante ao de saber quantas horas, minutos e segundos estão contidos num certo número de segundos. Assim, a nossa solução passa por saber a quantas páginas corresponde o nosso índice. Este valor obtém-se usando uma divisão inteira do nosso índice pelo número de células numa página. No entanto, com as páginas começam a 1, temos que adicionar precisamente 1 ao valor com a divisão. Sabida a página, vamos tentar saber a linha. Para isso temos que determinar primeiro qual o índice dentro da página, valor que se obtém do resto da divisão anterior. É este elemento que agora vai ser desdobrado pelas linhas. Como cada linha tem C colunas é por C que temos que dividir o valor do resto. Também aqui, porque a linha começa a 1, temos que adicionar um ao resultado. Finalmente, falta conhecer a posição (coluna) dentro da linha. Repetimos a estratégia: primeiro usamos o valor do resto da última divisão. Calculando o resto deste valor, quando o dividimos pelo número de células numa linha, obtemos o resultado final pretendido.

Como se vê este problema resolve-se basicamente com divisões inteiras e cálculo do resto. Entendido isto, listemos o código.


# Entrada dos dados
pos = input("posição: ")
L = input("Linhas: ")
C = input("Colunas: ")
# página
pagina = (pos / (L * C)) + 1
print "pagina: ", pagina
# Linha
resto_pagina = pos % (L * C)
linha = resto_pagina / C + 1
print "linha: ", linha
# Coluna
resto_linha = resto_pagina % C
coluna = resto_linha % C
print "coluna: ", coluna

Tudo isto é muito bonito. Mas testarmos o programa em situações limite temos problema. Eis um exemplo:


posição: 15
Linhas: 5
Colunas: 3
pagina: 2
linha: 1
coluna: 0
>>>

Outro exemplo ainda:


posição: 6
Linhas: 5
Colunas: 3
pagina: 1
linha: 3
coluna: 0
>>>


Conclusão: se a célula estiver ou na última linha de uma página ou na última coluna de uma linha, temos erro! É fácil de ver que isso ocorre quando alguma das divisões dá resto zero. Em breve aprenderemos a usar estruturas de controlo condicionais que nos permitirão resolver estes casos marginais.

4 comentários:

  1. Boa noite....

    Gostava que desse uma vista de olhos no programa que elaborei quando resolvi este exercício:

    def pag_linha_col ( x , y):
    """
    Dada as dimensões de uma página X e Y, calcula em que posição Linha, Coluna e Página o elemento pretendido se encontra
    """
    posicao = input ('Qual é a posição pretendida?')

    if posicao % (x * y) == 0:

    pag = posicao / (x * y)
    linha = x
    col = y

    else:

    pag = posicao / (x * y) + 1

    if (posicao % (x * y)) % y == 0:
    linha = posicao % (x * y) / y
    col = 1

    else:
    linha = (posicao % (x * y)) / y + 1
    col = posicao % (x * y) % y

    print "A linha em que se encontra é" , linha
    print "A Coluna em que se encontra é" , col
    print "A Pagina em que se encontra é" , pag

    Qual a sua opinião? Detectou algum erro? O que é que tenho de melhorar?

    Cumprimentos
    Gonçalo Pereira

    ResponderEliminar
  2. Admitindo que a indentação do código está correctamente feita, parece que o programa funciona. Eu apenas melhoraria coisas como não ter expressões longas e de alguma complexidade na leitura como: (posicao % (x * y)) % y == 0. Procuraria dar nomes intermédios, tipo:

    celulas_por_pagina = x * y

    posicao_na_pagina = posicao % celulas_por_pagina

    Já agora: existe uma solução sem ifs que consegue tratar dos casos limite.

    ResponderEliminar
  3. Será que podemos simplesmente tirar 1 ao número da posição e somar depois? Isto é,...

    pagina = (pos - 1) % (L*C) + 1

    ...e depois agir de forma equivalente nos outros valores a encontrar. Parece-me funcionar, pelo menos...

    ResponderEliminar