我正在嘗試使用Haskell簡單的遞回max演算法進行分析:
max_tag :: Integer -> [Integer] -> Integer
max_tag head [] = head
max_tag head (x:xs) =
let {m = max_tag x xs} in
let {b = (Prelude.<=) m head} in
case b of {True -> head; False -> m}
當我將它與 python 命令式等價物進行比較時,我得到了10 倍的速度因子來支持 python:
with open("input.txt") as fl:
data = [int(d) for d in fl.read().splitlines()]
max_ = 0
for d in data:
if max_ < d:
max_ = d
print(max_)
- 在這種情況下使用尾遞回似乎有一個固有的限制,對嗎?
Haskell - 還有其他方法可以使 Haskell 代碼更快嗎?
- 輸入檔案包含
1M無符號無界整數(平均 32 位)
為了完整起見,這是完整的Haskell檔案(不確定是否需要):
import Max
import System.IO
import Control.Monad
import System.Environment
import Prelude
readInt :: String -> Integer
readInt = read
max_tag :: Integer -> [Integer] -> Integer
max_tag head [] = head
max_tag head (x:xs) =
let {m = max_tag x xs} in
let {b = (Prelude.<=) m head} in
case b of {True -> head; False -> m}
main = do
args <- getArgs
contents <- readFile "input.txt"
let numbers_as_strings = words $ contents
let numbers = map readInt numbers_as_strings
let max_number = max_tag 0 numbers
print max_number
編輯:@Willem Van Onsem 建議的重構,有效!(28 秒 -> 12 秒)
max_bar :: Integer -> [Integer] -> Integer
max_bar head [] = head
max_bar head (x:xs) =
let {b = head < x} in
let {m = case b of {True -> x; False -> head}} in
max_bar m xs
關于進一步改進的任何想法?我必須比 python 快!
uj5u.com熱心網友回復:
使用它來對您的函式進行基準測驗應該使它運行得更快(也一定要使用text2.0 或更高版本):
import qualified Data.Text as T
import qualified Data.Text.IO as T
import qualified Data.Text.Read as T
readInt :: T.Text -> Integer
readInt t =
case T.signed T.decimal t of
Right (x, _) -> x
main :: IO ()
main = do
args <- getArgs
contents <- T.readFile "input.txt"
let numbers_as_strings = T.words contents
let numbers = map readInt numbers_as_strings
let max_number = max_tag 0 numbers
print max_number
max_tag您還可以通過使其尾遞回來加速函式本身,從而避免大量記憶體分配:
max_tag :: Integer -> [Integer] -> Integer
max_tag head [] = head
max_tag head (x:xs)
| x <= head = max_tag head xs
| otherwise = max_tag x xs
您可以通過使用使其更快一些,foldr以便獲得 foldr/build 融合map readInt:
max_tag :: Integer -> [Integer] -> Integer
max_tag x0 xs = foldr (\x go y -> if x > y then go x else go y) id xs x0
uj5u.com熱心網友回復:
比@Noughtmare 的答案更有效的方法是使用Data.ByteString沒有處理編碼開銷的方法,這里不需要。在我的測驗中,輸入一百萬個隨機的 32 位數字,運行時間約為 290 毫秒,而@Noughtmare 的答案運行時間約為 1020 毫秒。相比之下,原始 Python 的運行時間約為 560 毫秒。
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as C
import Data.Maybe (fromJust)
-- NOTE: This will throw an error if parsing fails.
readInt :: B.ByteString -> Integer
readInt = fst . fromJust . C.readInteger
main :: IO ()
main = do
contents <- B.readFile "read-integers.txt"
let numbers = map readInt $ C.lines contents
print $ max_tag 0 numbers
max_tag :: Integer -> [Integer] -> Integer
max_tag head [] = head
max_tag head (x : xs) = max_tag (max head x) xs
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/487870.html
