quarta-feira, 23 de março de 2011

O problema dos romanos

Olá, pessoal. Quanto tempo, hein?
Bom, após vários meses sem postar nada, aqui estou eu de novo pra falar sabe do que? Advinha, a resolução de um probleminha com o auxílio da linguagem Python.
O negócio é o seguinte: lá na Roma antiga, ao invés do pessoal usar os algarismos arábicos (i.e. 1, 2, ...), eles tinham sua própria forma de representar os números, por meio dos algarismos romanos. Daí, surgiu a ideia de eu criar uma função que recebesse um número inteiro como argumento e retornasse o seu correspondente romano.
Após algumas horas quebrando a cabeça, finalmente cheguei na lógica mais pythônica.

#!/usr/bin/python3.1
# coding: utf-8

__author__ = 'Luiz Augusto de M. Morais'
__date__ = '23.03.2011'
__version__ = '1.0.1'
__license__ = 'GPL'

romanos = {0: '', 1: 'I', 5: 'V', 10: 'X', 50: 'L', 100: 'C', 500: 'D', 1000: 'M'}

def converter(numero):
    """converter(numero) -> string
    A função converter recebe um número entre 0 e 4000 e o converte para
    seu número romano correspondente."""
    if 0 < numero <= 3999:
        romano = ''
        tamanho = len(str(numero)) - 1
        for algarismo in decompor(numero, tamanho):
            romano += romanizar(algarismo, 10 ** tamanho)
            tamanho -= 1
        return romano
    else:
        print('O número tem que estar no intervalo: 0 < numero <= 3999')


def decompor(numero, tamanho):
    """decompor(numero, tamanho) -> lista de algarismos
    A função decompor recebe um número como parâmetro e retorna as partes
    deste número (i.e. dezena, centena, etc.) em forma de lista.
    O parâmetro tamanho se refere ao tamanho do número (e.g. 100 -> 3)"""
    algarismos = []
    for digito in str(numero):
        algarismos.append(int(digito) * 10 ** tamanho)
        tamanho -= 1
    return algarismos
        

def romanizar(numero, ordem=1):
    """romanizar(numero [, ordem]) -> string
    A função romanizar recebe um número inteiro como parâmetro e
    retorna o número romano correspondente."""
    if numero in romanos.keys():
        romano = romanos[numero]
    elif numero < 4 * ordem:
        romano = numero // ordem * romanos[ordem]
    elif numero == 4 * ordem:
        romano = romanos[1 * ordem] + romanos[5 * ordem]
    elif numero < 9 * ordem:
        romano = romanos[5 * ordem] + (numero // ordem - 5) * romanos[ordem]
    elif numero == 9 * ordem:
        romano = romanos[ordem] + romanos[ordem * 10]
    return romano