ConverteExtenso.py 5.62 KB
#!/usr/bin/python
# -*- coding: utf-8 -*-

#Autor: Erickson Silva 
#Email: <erickson.silva@lavid.ufpb.br> <ericksonsilva@live.com>

#LAViD - Laboratório de Aplicações de Vídeo Digital

import sys
from unicodedata import normalize
from Iterator import *

num = {"zero":0, "um":1, "dois":2, "tres":3, "quatro":4, "cinco":5, "seis":6,
"sete":7, "oito":8, "nove":9}

ext = [{"um":"1", "dois":"2", "tres":"3", "quatro":"4", "cinco":"5", "seis":"6",
"sete":"7", "oito":"8", "nove":"9", "dez":"10", "onze":"11", "doze":"12",
"treze":"13", "quatorze":"14", "quinze":"15", "dezesseis":"16", 
"dezessete":"17", "dezoito":"18", "dezenove":"19"}, {"vinte":"2", "trinta":"3",
"quarenta":"4", "cinquenta":"5", "sessenta":"6", "setenta":"7", "oitenta":"8",
"noventa":"9"}, {"cento":"1", "cem":"1", "duzentos":"2", "trezentos":"3",
"quatrocentos":"4", "quinhentos":"5", "seissentos":"6", "setessentos":"7",
"oitocentos":"8", "novecentos":"9"}]

und = {"mil":1000, "milhao":1000000, "bilhao":1000000000, "trilhao":1000000000000}
unds = {"mil":"000", "milhao":"000000","milhoes":"000000", "bilhao":"000000000","bilhoes":"000000000", "trilhao":"000000000000", "trilhoes":"000000000000"}

def int_to_roman(input):
    if not isinstance(input, type(1)):
        raise TypeError, "expected integer, got %s" % type(input)
    if not 0 < input < 4000:
        raise ValueError, "Argument must be between 1 and 3999"
    ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
    nums = ('M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I')
    result = []

    for i in range(len(ints)):
        count = int(input / ints[i])
        result.append(nums[i] * count)
        input -= ints[i] * count
    return ''.join(result)

def roman_to_int(input):
    if not isinstance(input, type("")):
        raise TypeError, "expected string, got %s" % type(input)
    input = input.upper( )
    nums = {'M':1000,
            'D':500,
            'C':100,
            'L':50,
            'X':10,
            'V':5,
            'I':1}
    sum = 0
    for i in range(len(input)):
        try:
            value = nums[input[i]]
            if i+1 < len(input) and nums[input[i+1]] > value:
                sum -= value
            else: sum += value
        except KeyError:
            raise ValueError, 'input is not a valid Roman numeral: %s' % input
        
    if int_to_roman(sum) == input: return str(sum)
    else:
        raise ValueError, 'input is not a valid Roman numeral: %s' % input

def oneDigit(x):
	return ext[0][x]

def twoDigit(x):
	try:
		return ext[1][x[0]]+ext[0][x[1]]
	except:
		return ext[1][x[0]]+"0"

def threeDigit(x):
	return ext[2][x[0]]+ext[1][x[1]]+ext[0][x[2]]     

# Não faço mais a minima idéia de como fiz isso, só sei que funciona!
def extensoUnit(n):
    sn = n.split(",")
    size = len(sn)
    firstWord = sn[0]
    endWord = ""
    numExt = ""

    if(unds.has_key(sn[size-1])):
    	size -= 1
    	endWord = sn[size]
    	del sn[size]

    if(ext[0].has_key(firstWord)):
    	numExt = oneDigit(firstWord)
        
    elif (ext[1].has_key(firstWord)):
    	numExt = twoDigit(sn)

    elif (ext[2].has_key(firstWord)):
    	if(size == 1):
    		numExt = ext[2][firstWord]+"00"
    	elif (size == 2):
    		if(sn[1] == "dez"):
    			numExt = ext[2][firstWord]+oneDigit(sn[1])
    		try:
    			numExt = ext[2][firstWord]+"0"+oneDigit(sn[1])
    		except:
    			numExt = ext[2][firstWord]+twoDigit([sn[1]])
    	else:
	    	numExt = threeDigit(sn)

    if(endWord != ""):
    	numExt = numExt+unds[endWord]

    return numExt 


'''
Comece com uma lista vazia. Itere pelas palavras da string da esquerda 
para direita. Ao encontrar um numeral, adicione o número à lista se a 
última palavra foi uma escala, ou some ao último numero da lista se a 
última palavra foi um numeral. Ao encontrar uma escala, multiplique o 
último número da lista de acordo. Quando terminar, some tudo e retorne 
o resultado. 
'''

# TODO: Refatorar para nao usar mais o extensoUnit
def convert_extenso(extenso):
	global newToken, auxToken
	extensoQuebrado = extenso.lower().split(" ")
	if len(extensoQuebrado) == 1 and und.has_key(simplifica(extensoQuebrado[0])):
		return extenso
	nums = []
	it = Iterator()
	it.load(extensoQuebrado)
	while(it.has_next()):
		token = simplifica(it.get_token())
		tokenAnterior = simplifica(it.get_token(-1))
		if (und.has_key(token)):
			if(it.get_count() == 0):
				nums.append(und[token])
			else:
				newToken = und[token] * int(nums[-1])
				nums[-1] = newToken
		else:
			if (num.has_key(token)):
				auxToken = num[token]
			elif (not und.has_key(token)):
				auxToken = extensoUnit(token)
				
			if((not und.has_key(tokenAnterior)) and it.get_count() > 0):
				newToken = int(auxToken) + int(nums[-1])
				nums[-1] = newToken
			else:
				nums.append(auxToken)
	return soma(nums)

def soma(lista):
	soma = 0
	for i in lista:
		soma += int(i)
	return soma

def simplifica(txt):
	newToken = ""

	try:
		newToken = normalize('NFKD', txt.encode('utf-8').decode('utf-8')).encode('ASCII', 'ignore')
	except:
		newToken = normalize('NFKD', txt.encode('iso-8859-1').decode('iso-8859-1')).encode('ASCII','ignore')

	if(newToken[-3:] == "oes"):
		return newToken[:-3] + "ao"

	return newToken

# Test
'''
if __name__ == '__main__':
    n = sys.argv[1]
    return extenso(n)
    arquivoExts = open('exts', 'r')
    listaExts = arquivoExts.readlines()
    arquivoNums = open('nums', 'r')
    listaNums = arquivoNums.readlines()
    for i in range(0,500):
    	n = listaNums[i].replace("\n","")
    	e = listaExts[i].replace("\n","")
        numNew = extenso(e)
        if (str(numNew) != n):
        	print n + " != " + str(numNew)
        #else:
        #	print "OK: " + n + " == " + str(numNew)
'''