Listas e Strings – Exemplo Simples
6 Julho, 2008
Há alguns meses (em Maio, para ser mais exato), recebi uma mensagem de um estudante com um problema interessante para ser resolvido em Haskell. Dizia ele que o programa deveria receber como entrada um número de quatro dígitos e retorná-lo por extenso. Por exemplo, a entrada “0123″ deveria ter como resposta: “cento e vinte e três”. Como estou com tempo sobrando (já fechei quase todas as matérias do semestre), resolvi brincar um pouco com esse problema, o que gerou este post.
Resolvi então fazer uma função extenso, que recebe uma string com quatro caracteres e retorna uma string:
extenso ([x,y,z,w]) = mil(x) ++ cen([x, y,z,w]) ++ dec([y,z,w]) ++ if(z == '1')then "" else uni(w)
A linha acima diz que extenso é a concatenação de mil(x), cen([x, y,z,w]), dec([y,z,w]) e if(z == '1')then "" else uni(w), que basicamente seria a concatenação da parte dos milhares, das centenas, das dezenas e das unidades. O “if” no final é para que a parte das unidades só fosse processada quando o valor das dezenas fosse diferente de ‘1′ (quando a dezena vale 1, a unidade é tratada junto com a dezena).
Vamos ver as outras funções:
mil(x):
mil(x) = (case x of
'0' -> ""
'1' -> "mil"
'2' -> "dois mil"
'3' -> "tres mil"
'4' -> "quatro mil"
'5' -> "cinco mil"
'6' -> "seis mil"
'7' -> "sete mil"
'8' -> "oito mil"
'9' -> "nove mil")
A função acima retorna a parte dos milhares. é bem simples, apenas retorna a parte dos milhares por extenso (e “” para quando o valor dos milhares for zero).
cen([x, y,z,w]):
cen([x, y,z,w]) = (if(not(x=='0') && ((y=='0' && (not(z=='0') || not(w=='0'))) || not(y=='0') && z=='0' && w == '0'))then " e " else "") ++ (case y of
'0' -> ""
'1' -> (if (z == '0' && w == '0') then "cem" else "cento")
'2' -> " duzentos"
'3' -> " trezentos"
'4' -> " quatrocentos"
'5' -> " quinhentos"
'6' -> " seiscentos"
'7' -> " setecentos"
'8' -> " oitocentos"
'9' -> " novecentos") ++ if ((y=='0') || (z == '0' && w == '0')) then "" else " e "
Retorna a parte das centenas. o if inicial e o final tratam o aparecimento do “e” entre as palavras. Repare também no tratamento do ‘1′, que às vezes aparece como “cem” e outras como “cento”.
dec([y,z,w]):
dec([y,z,w]) = (case z of
'0' -> ""
'1' -> decDez(w)
'2' -> "vinte"
'3' -> "trinta"
'4' -> "quarenta"
'5' -> "cinquenta"
'6' -> "sessenta"
'7' -> "setenta"
'8' -> "oitenta"
'9' -> "noventa" ) ++ if(z == '0' || z== '1' || w == '0') then "" else " e "
decDez(w) = case w of
'0' -> "dez"
'1' -> "onze"
'2' -> "doze"
'3' -> "treze"
'4' -> "quatorze"
'5' -> "quinze"
'6' -> "dezesseis"
'7' -> "dezesete"
'8' -> "dezoito"
'9' -> "dezenove"
Aqui tratamos a parte das dezenas. Quando o valor for ‘1′, temos que fazer um tratamento especial, então usamos a função decDez(w). No final temos um if para tratar o uso do “e”.
uni(x):
uni(x) = case x of
'0' -> ""
'1' -> "um"
'2' -> "dois"
'3' -> "tres"
'4' -> "quatro"
'5' -> "cinco"
'6' -> "seis"
'7' -> "sete"
'8' -> "oito"
'9' -> "nove"
Finalmente, a função uni(x) cuida da parte das unidades.
Este problema é de fácil resolução, deixo como exercício para quem quiser brincar um pouco com listas. Bug do meu código: o valor “0000″ retorna “” (faltou tratar isso =P).
Tags: haskell, iniciantes, lista