在 Haskell 中查找长 Collatz 序列
Finding long Collatz sequences in Haskell
今天,我在 Haskell ...
中玩 Collatz 序列
这是我的代码:
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 ..] 上无限迭代。每次找到新的最大 Collatz 长度时,我都想在屏幕上显示它,然后继续。我不知道如何在 Haskell 中执行此操作,因为我必须在某处保留和更新最大长度值。
使用map
和无限范围
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)
后一种方法可以让您更好地控制循环。
请注意,每个循环都会从头开始计算序列号,而不会利用之前计算的结果。要获得更有效的方法,请查找 memoization(不要与 "memorization" 混淆)。这种技术允许程序 "remember" 以前计算的递归调用的结果,这样新的调用就不必重新计算相同的值。
如果要保留所有返回值的最大值,可以使用
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
But I do not want to print all the results. Only the lengths that are higher than the "current" maximum length.
然后,生成那些 "higher" 点的列表:
-- 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)
今天,我在 Haskell ...
中玩 Collatz 序列这是我的代码:
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 ..] 上无限迭代。每次找到新的最大 Collatz 长度时,我都想在屏幕上显示它,然后继续。我不知道如何在 Haskell 中执行此操作,因为我必须在某处保留和更新最大长度值。
使用map
和无限范围
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)
后一种方法可以让您更好地控制循环。
请注意,每个循环都会从头开始计算序列号,而不会利用之前计算的结果。要获得更有效的方法,请查找 memoization(不要与 "memorization" 混淆)。这种技术允许程序 "remember" 以前计算的递归调用的结果,这样新的调用就不必重新计算相同的值。
如果要保留所有返回值的最大值,可以使用
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
But I do not want to print all the results. Only the lengths that are higher than the "current" maximum length.
然后,生成那些 "higher" 点的列表:
-- 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)