Project Euler 8 - Haskell

后端 未结 2 1854
深忆病人
深忆病人 2021-01-21 12:58

Going through Project Euler I am comparing my solutions to the ones here.

For question 8 my code produces the correct answer (confirmed via the check sum on the website)

相关标签:
2条回答
  • 2021-01-21 13:14

    What is happening is that digitToInt returns an Int, which on 32-bit systems is too short to hold the test numbers when 5 is increased to 13. Change it to (fromIntegral . digitToInt) and it works correctly.

    0 讨论(0)
  • 2021-01-21 13:20

    The problem was already identified as an Int overflow, but the wiki code itself is incorrect. It doesn't truncate the list properly, and might produce incorrect result, depending on input data (i.e. it produces the correct result here by a lucky chance).

    Imagine a string of digits which ends in a 0 followed by 12 9s. The code will take 9^12 into consideration incorrectly, when calculating the maximum value. Even simpler, for a 1000 zeroes it will produce 1 as an answer.

    We can achieve an automagical truncation, due to the properties of zipping:

    import Data.Char
    import Data.List
    
    euler_8 = do
       str <- readFile "numbers.txt"
       print . maximum . map product
             . foldr (zipWith (:)) (repeat [])   -- here
             . take 13 . tails . map (fromIntegral . digitToInt)
             . concat . lines $ str
    

    Your code though is correct, but has some issues:

    • [x | x <- xs] is just xs
    • last (sort xs) is just maximum xs, which is faster
    • appending on the right of a recursive call is a known source for inefficiency. it is better even to append on the left and reverse in the end, but the following transformation is more Haskellian:
    toDigits n xs  -- to be called as `toDigits n []`
     | n < 1 = xs
     | otherwise = toDigits (n `div` 10) ((n `mod` 10) : xs)
    
    0 讨论(0)
提交回复
热议问题