微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在Haskell中解析大型矩阵

如何解决在Haskell中解析大型矩阵

我最近开始学习Haskell,正在测试我使用Google KickStart代码挑战学到的东西。

我正在查看的problem本质上要求从标准输入中读取平方矩阵,并对与主对角线平行的对角线上的元素求和。 我编写了一个简单的程序来解决该问题,该程序通过了第一个测试,但未通过第二个测试。 问题似乎是第二个测试中的输入比第一个测试大得多,并且我编写的解析器太慢或使用了太多内存。

输入被格式化为一系列矩阵

n
a11 ... a1n
...
an1 ... ann

我第一次尝试使用内置函数

type Matrix = [[Int]]

parseInput:: String -> [Matrix]
parseInput = parseInput' . lines
    where
        parseInput':: [String] -> [Matrix]
        parseInput' [] = []
        parseInput' (i:is) = let (m,rest) = splitAt (read i) is in
                                 (map ((map read).words) m) : (parseInput' rest)

main = do
    input <- getContents
    let result = show $ parseInput input
    putStr result

第二次尝试使用parsec库

import Text.Parsec
import Text.Parsec.String (Parser)

type Row = [Int]
type Matrix = [[Int]]

matrixSize::(Integral a,Read a) => Parser a
matrixSize = do
    n <- ( many1 digit ) <* newline
    return $ read n

matrixRow:: Parser Row
matrixRow = do
    row <- (sepBy1 (many1 digit) (char ' ')) <* (newline <|> (eof >> return ' '))
    return $ map read row

parseMatrix:: Parser Matrix
parseMatrix = do
    n <-  matrixSize
    mat <- count n matrixRow
    return mat

parseInput:: Parser [Matrix]
parseInput = (many1 parseMatrix)

prepareInput:: String -> [Matrix]
prepareInput input = case parse parseInput "" input of
                       Right l -> l
                       Left _ -> []

main = do
    input <- getContents
    let result = show $ prepareInput input
    putStr result

根据Google网站,第二个测试实例最多包含100个矩阵,其中10个的大小最大为1000,元素的大小最大为10 ^ 7,其余的矩阵的大小最大为100。

生成一个random test file,其中包含10个大型矩阵,大小最多为1000,结果大约是30MB。 在测试文件上运行任何一个解析器在我的计算机上大约需要13s,第二个使用超过1GB的内存。 两者都无法满足在服务器上运行的要求:第一个超过20秒的执行时间,第二个则超过1GB的内存限制。

是否有更好的解析大文件方法? 在我的代码中是否可以解决任何效率低下的问题?

任何建议将不胜感激!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。