sábado, 16 de janeiro de 2010

Metarmofoses

Will McGugan é um conhecido programador de Python, especialista no desenvolvimento de jogos. Mas também trabalha na selecção de candidatos a emprego onde o conhecimento de Python é importante. No seu blogue dá conta de duas questões tipo que costuma colocar aos candidatos. A primeira é a seguinte. Suponha que precisa de desenvolver um programa que receba como parâmetro um número inteiro e devolva uma cadeia de caracteres que representa o número, mas onde foram colocadas vírgulas para marcar os milhares.

Por exemplo:

>>> milhares_com_virgulas(1234)
'1,234'
>>> milhares_com_virgulas(123456789)
'123,456,789'
>>> milhares_com_virgulas(12)
'12'

Estes exemplo são elucidativos do que se pretende e também dos casos que têm que se ter em conta. Existem várias maneiras de resolver o problema. Pense um pouco antes de olhar para a solução e procure desenvolver a sua solução.


def milhares_com_virgulas(num):
# muda representação
cadeia = list(str(num))
# calcula resultado
resultado = ''
while len(cadeia) > 3:
aux = ',' + ''.join(cadeia[len(cadeia)-3:])
resultado = aux + resultado
cadeia = cadeia[:-3]
resultado = ''.join(cadeia)+ resultado
return resultado

A nossa solução faz uso de uma mudança de representação e dos comandos str, list e join para comutar entre números, listas e cadeias de caracteres. Socorre-se também de uma variável acumulador onde vamos construindo o resultado.

3 comentários:

  1. Algo que me ocorreu sem grande porquê, a quem interesse:
    O principal problema que encontrei na programação, nesta cadeira, é a fase da resolução de problemas: Perceber o problema, e como resolve-lo, é obviamente importante, mas mais difícil de fazer do que parece, e o resultado é dar voltas desnecessárias, duplicando ou triplicando as linhas de código, e exponenciando a probabilidade de nos "perdermos"..

    ResponderEliminar
  2. def milhares_com_virgulas(numero):
    num=str(numero)
    li=[]
    for i in range(0,len(num)+1,3):
    li.append(num[i:i+3])
    string=','.join(li)
    return string

    Não é uma solução correcta visto que conta do inicio para o fim e não do fim para o inicio como fazemos para contar milhares e separar. Mas como seria uma possivel resoluçao partindo desta ideia. Não consigo resolver...
    Obrigado :)

    ResponderEliminar
  3. Realmente o seu programa é uma boa aproximação. Mas tem alguns problemas. O ciclo for não é a melhor solução pois obriga a muita ginástica! Mas comecemos pela questão da ordem. Basta percorrer o número do fim para o princípio:

    def milhares_com_virgulas(numero):
    num=str(numero)
    li = []
    for i in range(len(num),0,-3):
    li.append(num[i-3:i])
    string = ','.join(li[::-1])
    return string


    Mas ficamos com o problema da parte inicial por resolver. Basta experimentar com um número com menos de três dígitos. Então, temos que prever esse caso:

    def milhares_com_virgulas(numero):
    num=str(numero)
    if len(num) < 3:
    return str(num)
    else:
    li = []
    for i in range(len(num),0,-3):
    li.append(num[i-3:i])
    aux = len(num)%3
    string = num[:aux] + ','.join(li[::-1])
    return string


    E pronto, agora funciona.

    Mas existe uma outra solução, mais elegante. Só que é recursiva... Aqui vai, para quem se interessa por estas coisas:

    def milhares_com_virgulas_rec(numero):
    if numero == 0:
    return ''
    elif numero < 1000:
    return str(numero)
    else:
    return milhares_com_virgulas(numero/1000) + ',' + str(numero%1000)


    notar como partimos o número em duas partes: uma primeira com todos os dígitos menos os três últimos, e uma segunda com o três últimos dígitos. Notar como garantimos que o 0 não dá problema. Espero ter ajudado!

    ResponderEliminar