Python faster than Haskell in a Code Jam problem? (d1000000)

Viewed 174

This problem involves an arbitrary number of dice with each an arbitrary number of sides. We then find the maximal number of dice that can be put in a straight, see Google's Code Jam explanation. The implementation should be reasonably efficient for around 10^5 dice with each one having up to 10^6 sides.

I've been trying to solve the problem in Haskell and this is my solution. However, it is not fast enough to earn full points on the problem, so can this be optimized?

import Data.List (sort)
import Data.Foldable (foldl')

getMaxStraight :: [Int] -> Int
getMaxStraight sides =
  foldl'
    (\maxStraight side -> if side > maxStraight then succ maxStraight else maxStraight)
    0
    (sort sides)

-- Doing IO in Haskell
-- Assuming the above works perfectly, something might not perform well below

main :: IO ()
main = do
  line <- getLine :: IO String
  let numberOfCases = read line :: Int
   in mapM_ solveCase [1 .. numberOfCases]

solveCase :: Show a => a -> IO ()
solveCase i = do
  line1 <- getLine :: IO String
  line2 <- getLine :: IO String
  let numberOfDice = read line1 :: Int
  let diceSides = map read (words line2) :: [Int]
  let maxStraight = getMaxStraight diceSides
  putStrLn $ "Case #" ++ show i ++ ": " ++ show maxStraight

Aside from this, I've also written a Python solution which did run in time. I'd expect that Haskell would run faster than Python. What is going on?

def get_max_straight(sides):
    max_straight = 0
    for side in sorted(sides):
        if side > max_straight:
            max_straight += 1
    return max_straight

# Doing IO in Python
# This works as needed

if __name__ == '__main__':
    tests_len = int(input())
    for case_num in range(1, 1 + tests_len):
        input() # Discard unneeded input
        sides = [int(s) for s in input().split(' ')]
        print(f'Case #{case_num}: {get_max_straight(sides)}')
0 Answers
Related