[英]How to define an infinite 2D array recursively in Haskell?
我是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 ...
...
我知道如何定義一個簡單的函數:
pascal :: Int -> Int -> Int
pascal 1 _ = 1
pascal _ 1 = 1
pascal x y = (pascal (x - 1) y) + (pascal x (y - 1))
由於Haskell不記憶函數值,因此調用pascal 20 20
需要很長時間 。 我怎么能定義一個快速版本(如無限的2D數組)?
您可以將pascal三角形創建為無限,惰性,嵌套列表
pascal :: [[Integer]]
pascal = repeat 1 : map (scanl1 (+)) pascal
上面的定義有點簡潔,但它本質上意味着每一行都是前一行的累加和,從repeat 1
開始,即無限的列表。 這樣做的好處是我們可以直接計算三角形中的每個值而無需進行任何O(n)索引。
現在,您可以索引列表以查找所需的值,例如
> pascal !! 19 !! 19
35345263800
該列表僅針對您需要的值進行部分評估。
您還可以輕松輸出一系列值:
> 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
另一種選擇是使用原始功能,但使用可用的各種記憶庫之一進行記憶。 例如,使用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))
無限2D“數組”的明顯選擇是嵌套列表,即無限列表的無限列表。 因此可能是
pascal' :: [[Integer]]
pascal' = repeat 1 : [ 1 : [ pascalGen x y | y<-[1..] ] | x<-[1..] ]
where pascalGen x y = pascal' !! (x-1) !! y + pascal' !! x !! (y - 1)
現在這個函數調用了memoised。 由於列表O ( n )訪問,它仍然不是最優的,但也不是那么糟糕。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.