flyinggit's blog

By flyinggit, history, 19 months ago, In English

I got into using CodeForces a few weeks ago, using Haskell for the last two competitions. I spent hours debugging three Haskell quirks in the competitions, so I hope this saves time for future Haskellers!

  1. Do NOT use default getContents or getLines in CodeForces. I found that at least one of my solutions per competitions will TLE even if I have the perfect algorithm. The issue was not my algorithm, it was the I/O time. Switching to getContents or getLines from Data.ByteString.Char8 fixed these issues.

I usually do something like

import qualified Data.ByteString.Char8 as BS

main = do
    n <- fst . fromJust . BS.readInt <$> BS.getLine
    forM [1..n] $ \_ -> do
        input <- BS.getLine
        -- logic
  1. STRIP OUT '\r' from the end of the output of Data.ByteString.Char8.getLine. I spent hours trying to figure out why my one of my string-based algorithms worked on my laptop, but not CF. It turns out that newlines on CF are \r\n, while my MacBook uses just \n. Using Data.ByteString.Char8.getLine on CodeForces resulted in \r at the end of the line, which added an extra "\r" element in my strings on CF only.

I usually do

BS.filter (/= '\r') myByteString

to strip the line. BS.strip does exist, but the version of byte string in the CF Haskell environment is outdated and does not have BS.strip.

  1. (less important) Unlike Python or C, Haskell does not have a built-in heap or priority queue implementation. It turns out that ordered sets will be close to what you want. The only issue is that sets can only hold distinct values, so if your heap will have multiple of the same elements, you need to store tuples of (value, iterationCount) in the set. The heap will first use value to order the heap, but if there are multiple of the same value it will use iterationCount to distinguish the values. https://hackage.haskell.org/package/heaps-0.4.1/docs/Data-Heap.html seems like a good heap implementation that would remove the need to add the iterationCount boilerplate, but understandably it is not part of the CF GHC environment.
  • Vote: I like it
  • +2
  • Vote: I do not like it

| Write comment?
»
19 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

This is amazing! I don't use Haskell for competitive programming however it's been a language that's made me very curious over the years, I've done a few experiments with it and solved some Project Euler problems with it.

Why choose Haskell over other say C++ or Python in a contest though? (Although honestly if I had a better grasp of it, I would use it too, perhaps not over C++, however I am just much more skilled in C++)

  • »
    »
    19 months ago, hide # ^ |
     
    Vote: I like it +1 Vote: I do not like it

    Thanks! I am hoping that repeatedly using Haskell on hard problems will help me learn and internalize category theory.

    I spend most of my career re-learning the same decision framework in slightly different contexts. If it is possible to abstract decision making to a higher level through math like category theory, then I can focus on making truly novel decisions at work.

»
19 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

The root cause of the problem is that interact/getContents uses String and the way it implemented is very slow on large strings