Resolvendo problema do URI Online Judge em Haskell

4 minute read

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.

Updated: