在Haskell中找到长的Collat​​z序列

时间:2017-05-20 07:42:42

标签: haskell collatz

今天,我正在玩Haskell中的Collat​​z序列...

这是我的代码:

collatzLength :: Int -> Integer -> Int
collatzLength count 1 = count
collatzLength count n = collatzLength (count+1) $ if n `mod` 2 == 0 then n `div` 2 else 3*n+1

main =
    print (collatzLength 1 (10^10000 + 1))

我想做的是在[1,3]上无限迭代。每次找到新的最大Collat​​z长度时,我想在屏幕上显示它,然后继续。我不知道如何在Haskell中做到这一点,因为我必须在某处保持并更新最大长度值。

1 个答案:

答案 0 :(得分:2)

使用main = print $ map (collatzLength 1) [1,3..] 和无限范围

main :: IO ()
main = loop 1

loop :: Int -> IO ()
loop n = do
   print (collatzLength 1 n)
   loop (n+2)

或使用显式递归

loop :: Int -> Int -> IO ()
loop n prevMax = do
   let m = collatzLength 1 n
   putStrLn $ "collatzLength 1 " ++ show n ++ " = " ++ show m
   let nextMax = max prevMax m
   putStrLn $ "current maximum = " ++ show nextMax
   loop (n+2) nextMax

后一种方法可以让你对循环有更好的控制。

请注意,每个循环都会从头开始计算序列号,而不会利用以前计算的结果。为了更有效的方法,请查找memoization(不要与" memorization"混淆)。这些技术使程序能够记住"先前计算的递归调用的结果,以便新调用不必重新计算相同的值。

如果要保留所有返回值的最大值,可以使用

-- Assumes a list of positive numbers.
-- Returns the list of those elements which are larger than all the
-- previous ones.
highPoints :: [Int] -> [Int]
highPoints xs = go 0 xs
   where
   go :: Int -> [Int] -> [Int]
   go _          []     = []
   go currentMax (n:ns) | n > currentMax = n : go n ns
                        | otherwise      = go currentMax ns

main :: IO ()
main = do 
   let collatzSequence :: [Int]
       collatzSequence = map (collatzLength 1) [1,3..]
   print (highPoints collatzSequence)
  

但我不想打印所有结果。只有长度高于"当前"最大长度。

然后,生成一个列表"更高"分:

$("ul a.toggle").click(function() {
  $(this).next("ul").slideToggle();
});