我是Haskell的新手,我喜欢它优雅的语法.但我还没有找到一种合适的方法来定义无限的2D数组 - 例如,Pascal三角形:
1 1 1 1 1 ...
1 2 3 4 5 ...
1 3 6 10 15 ...
1 4 10 20 35 ...
1 5 15 35 70 ...
...
Run Code Online (Sandbox Code Playgroud)
我知道如何定义一个简单的函数:
pascal :: Int -> Int -> Int
pascal 1 _ = 1
pascal _ 1 = 1
pascal x y = (pascal (x - 1) y) + (pascal x (y - 1))
Run Code Online (Sandbox Code Playgroud)
由于Haskell不记忆函数值,因此调用pascal 20 20将花费很长时间.我怎么能定义一个快速版本(如无限的2D数组)?
您可以将pascal三角形创建为无限,惰性,嵌套列表
pascal :: [[Integer]]
pascal = repeat 1 : map (scanl1 (+)) pascal
Run Code Online (Sandbox Code Playgroud)
上面的定义有点简洁,但它本质上意味着每行都是前一行的累加和,从repeat 1无限的列表开始.这样做的好处是我们可以直接计算三角形中的每个值而无需进行任何O(n)索引.
现在,您可以索引列表以查找所需的值,例如
> pascal !! 19 !! 19
35345263800
Run Code Online (Sandbox Code Playgroud)
该列表仅针对您需要的值进行部分评估.
您还可以轻松输出一系列值:
> putStrLn $ unlines $ take 5 $ map (unwords . map show . take 5) $ pascal
1 1 1 1 1
1 2 3 4 5
1 3 6 10 15
1 4 10 20 35
1 5 15 35 70
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用原始功能,但使用可用的各种记忆库之一进行记忆.例如,使用data-memocombinators:
import Data.MemoCombinators
pascal :: Integer -> Integer -> Integer
pascal = memo2 integral integral pascal'
pascal' :: Integer -> Integer -> Integer
pascal' 1 _ = 1
pascal' _ 1 = 1
pascal' x y = (pascal (x - 1) y) + (pascal x (y - 1))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
654 次 |
| 最近记录: |