【问题标题】:performance issue on collatz chaincollat​​z链上的性能问题
【发布时间】:2011-07-04 23:04:34
【问题描述】:

我有一个工作程序来计算给定范围内最长的 collat​​z 链(项目 euler n°14)。我认为它可以正常工作,但速度很慢。我试图寻找更好的解决方案,但我只能稍微减少评估域。我做错了吗?

该实现使用记忆化来避免两次计算相同的结果。 Data.Map 对一般性能不利吗?

import Data.Map ((!), member, insert, singleton, assocs, Map)

insertSolution::Integer->(Map Integer Integer)->(Map Integer Integer)
insertSolution n syracMap
    | n `member` syracMap = syracMap
    |otherwise = let
        next = if n `mod` 2 == 0 then n `div` 2 else 3 * n + 1
        newMap = insertSolution next syracMap
        solution = newMap ! next + 1
        in insert n solution newMap

bound = 1::Integer
lower = 999999::Integer

test::[Integer]
test = [lower,lower+2..bound]

values = takeWhile (\(k, v) -> k < bound) $ assocs $ foldr insertSolution (singleton 1 1) test

result = foldr (\(k, v) (k', v') -> if v > v' then (k, v) else (k', v')) (1, 1) values

main = putStr $ show $ result

编辑

更新功能以消除错误。我的笔记本电脑还是很慢。

【问题讨论】:

  • 我可以看到的一个问题是您正在递归调用insertSolution(在您的变量newMap),但在旧地图而不是更新地图上。这不允许共享。不知道是不是故意的。
  • 不,不是。我将测试新版本。谢谢你的评论。
  • 我最近开始使用 data-memocombinators 进行我的 Project Euler 尝试。您可能想尝试一下...

标签: performance haskell


【解决方案1】:

FWIW,这是我的解决方案:

module Main
    where

import Data.List
import Data.Ord

next_hailstone n | even n = n `div` 2
                 | otherwise = 3*n+1

gen_next_hailstone n
    = if nh == 1
      then Nothing
      else Just (nh, nh)
          where nh = next_hailstone n

hailstone n = unfoldr gen_next_hailstone n

hailstone_seqs = map hailstone [1..1000000]

zip_hailstone = zip [1..1000000] hailstone_seqs

max_hailstone = maximumBy (comparing (length . snd)) zip_hailstone

main = print . fst $ max_hailstone

相对较快。如果你想要更快的速度,consult the Haskell wiki剧透警告!!!)。

【讨论】:

  • 如果我没看错,那就是蛮力法。在您的链接中,某些版本具有数组或列表的记忆。有什么理由不通过地图使用记忆?
  • 为什么要使用地图?数组是O(1)访问,Map是O(log n),你不用关心数组更新。
  • 感谢您的建议。但我关心数组更新,因为我将所有结果都存储在里面。您能否更具体地说明这一点?我看事物的方式,结果不是连续的(索引不是[0..n]的形式),所以我不能使用数组。我会测试你的链接。
  • Haskell Wiki 中的Array 解决方案使用listArray 一步生成整个数组并且从不更新它——这就是我所说的“你不关心数组更新”的意思。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-08
  • 1970-01-01
  • 1970-01-01
  • 2016-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多