可以对此Haskell代码进行哪些优化?

时间:2016-02-05 02:27:32

标签: haskell optimization

--Returns last N elements in list
lastN :: Int -> [a] -> [a]
lastN n xs = let m = length xs in drop (m-n) xs

--create contiguous array starting from index b within list a
produceContiguous :: [a] -> Int -> [[a]]
produceContiguous [] _ = [[]]  
produceContiguous arr ix = scanl (\acc x -> acc ++ [x]) [arr !! ix] inset
    where inset = lastN (length arr - (ix + 1)) arr

--Find maximum sum of all possible contiguous sub arrays, modulo [n]
--d is dummy data
let d = [1,2,3,10,6,3,1,47,10]
let maxResult = maximum $ map (\s -> maximum s) $ map (\c -> map (\ac -> (sum ac )`mod` (last n)) c ) $ map (\n -> produceContiguous d n ) [0..(length d) -1]

我是一个Haskell newb - 就在几天之内......如果我做了一些明显错误的事情,那就哎呀

1 个答案:

答案 0 :(得分:6)

您可以通过观察map sum (produceContiguous d n)(其运行时间为Ω(m ^ 2),长度为drop n d - 可能为O(立方米)时间来改善运行时间,因为您'在每次迭代时附加到acc的末尾)可以折叠为scanl (+) 0 (drop n d)(具有运行时O(m))。我还会做出很多其他的风格变化,但这是我能想到的主要算法。

清理所有风格的东西,我可能会写:

import Control.Monad
import Data.List
addMod n x y = (x+y) `mod` n
maxResult n = maximum . (scanl (addMod n) 0 <=< tails)

在ghci:

*Main> jaggedGoofyMax 100 [1..1000]
99
(12.85 secs, 24,038,973,096 bytes)
*Main> dmwitMax 100 [1..1000]
99
(0.42 secs, 291,977,440 bytes)

此处未显示的是jaggedGoofyMax的版本,其我在应用的第一段中提到的优化,其对dmwitMax的运行时/内存使用情况统计略好一些当在ghci中运行时(但当使用dmwitMax编译时,基本上与-O2相同)。因此,您可以看到,即使是适度的输入大小,这种优化也会产生很大的不同。