Resolvendo problema do URI Online Judge em Haskell
O URI Online Judge é um serviço fantástico. Ele fornece um número muito grande de problemas de programação, e podemos resolvê-lo em diversas linguagens. Nossas soluções são julgadas por um juiz automático, o que é muito prático e útil para usar em disciplinas de programação.
Recentemente comecei a ministrar a disciplina de Programação Funcional, e é claro que eu quero tentar usar o URI Online Judge novamente na minha disciplina, mas usá-lo com a linguagem Haskell parece ser um pouco traiçoeiro. Seguem algumas dicas se você estiver tentando fazer o mesmo.
A estrutura básica do programa
O seu programa precisa ter essa estrutura básica para funcionar:
1
2
3
4
main :: IO ()
main = do
r <- getLine
-- demais linhas de código
Depois do do
você deve colocar todo o código do seu programa. A linha 3 é só um exemplo, você vai substituí-la pelo que você precisa de acordo com o problema a ser resolvido.
Obtendo entradas
Todos os problemas envolvem a entrada de dados, então você vai precisar recebê-los de alguma forma. A forma que tem funcionado para mim é receber o valor com a função getLine
e depois fazer a conversão que precisar mais adiante. Teremos um exemplo mais adiante que inclui todos os detalhes que estou mostrando aqui.
Convertendo valores
Para converter valores a forma mais simples usamos a função read
. Se você quer converter uma String lida do teclado para o tipo Double, pode fazer assim:
1
numero m = read m :: Double
Sempre que precisar converter uma String para um valor de ponto flutuante é só invocar essa função passando a String como argumento. Neste exemplo estou usando o tipo Double, mas você pode mudar para tipo que for necessário para o problema. Alguns problemas podem ter casos de teste com números bem grandes, então recomendo usar o tipo Double quando houver essa possibilidade ou você estiver recebendo a mensagem de Wrong answer.
Imprimindo valores
Estou usando a função putStrLn
, e até agora não tive problema de “Presentation error”. Quem já usou o URI Online Judge sabe como isso é chatinho às vezes. A função printf
é bastante útil, pois ela nos ajuda a fazer a formatação da saída. É muito comum precisarmos definir uma quantidade de casas decimais no resultado, e podemos fazer isso passando uma string de formato como primeiro parâmetro. Veremos um exemplo abaixo.
Exemplo com tudo junto
Aqui está um exemplo completo. Este programa faz o cálculo do volume de uma esfera. Ele recebe o raio como entrada e imprime na tela o resultado.
1
2
3
4
5
6
7
8
9
10
11
12
import Text.Printf
pi' = 3.14159
numero m = read m :: Double
volume r = 4.0/3.0 * pi' * r ** 3
main :: IO ()
main = do
r <- getLine
putStrLn ("VOLUME = " ++ printf "%.3f" (volume (numero r)))
Nesse problema eu defini um valor de Pi específico, pois assim o problema pediu. Se eu não tivesse feito isso, provavelmente as minhas respostas não bateriam com os casos de teste, pois a precisão do Pi na biblioteca padrão do Haskell é bem maior. Coloquei ele como o nome pi'
(com apóstrofo) para evitar a ambiguidade com o pi
sem apóstrofo, da biblioteca padrão.
Criei também a função volume
, que recebe apenas o raio e faz o cálculo do volume da esfera.
Para imprimir o resultado usei a função printf
, passando “%.3f” como o primeiro argumento, informando que eu quero a saída como um número de ponto flutuante com 3 casas decimais. Para mais detalhes, consulte a documentação completa da função. IMPORTANTE: você precisa fazer import Text.Printf
para poder usar a função printf
. Ela tem um funcionamento muito semelhante ao que vemos nas versões do printf
do C e do Python.
Testando antes de submeter
Para testar antes de submeter você precisa compilar o programa. Eu uso o GHC, e sempre funciona muito bem. Após compilar, execute o programa de acordo com a sua plataforma. Usar o Hugs (GHCi) também é útil para testar as suas funções enquanto está construindo a solução, mas o teste definitivo sempre deve ser com o programa compilado.