haskell嵌套列表中的pascal三角形

时间:2018-05-03 00:59:29

标签: haskell pascals-triangle

我试图获取pascal列表中每个列表中的第k行。例如,pascal 4将获得每行中的第4个元素。所以它将返回1,4,10,20 ...等我理解如何构造一个无限的pascal列表,这是下面的输出,但我不确定如何在每个嵌套列表中获取第n个元素。有什么建议?我正在考虑使用地图,但我不一定在这里映射一个功能,这让我有点失望。谢谢。

// im trying to get pascal k to return the nth element of every row in the triangle
pascal n = map(\n -> ??) take n pascal 
pascal_infite = [1] : map (\l -> zipWith (+) (l ++ [0]) (0:l)) pascal_infinite

2 个答案:

答案 0 :(得分:2)

获取第k行:

>>> pascal_infinite !! 4
[1,4,6,4,1]

[0..k]获取所有行:

>>> map (pascal_infinite !!) [0..4]
[[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]

要从[0..k] 快速获取所有行

>>> take (4+1) pascal_infinite
[[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]
哎呀,误读了一下这个问题。为了得到你所要求的东西,如果你担心速度,你应该构建一个好的旧n choose k公式或类似的东西。

如果这只是一个练习,无视速度,这是一种方式:

pascal n = map (!! n) $ drop n pascal_infinite

然后简单地抽取几个第四个元素:

>>> take 8 $ pascal (4-1)
[1,4,10,20,35,56,84,120]

答案 1 :(得分:1)

这基本上是一个iterate :: (a -> a) -> a -> [a]函数,你有一个状态,每次更新状态,你就会产生一个元素列表。

作为迭代函数,我们基本上希望使用前一个列表zipWith (+)xs执行(0:xs),但我们会继续迭代,直到两个列表都用完为止。我们可以为此实现zipWithLongest

zipWithLongest :: a -> b -> (a -> b -> c) -> [a] -> [b] -> [c]
zipWithLongest x0 y0 f = go
    where go (x:xs) (y:ys) = f x y : go xs ys
          go [] t = map (f x0) t
          go t [] = map (flip f y0) t

现在我们可以使用:

生成列表
import Control.Monad(ap)

pascalTriangle :: Num n => [[n]]
pascalTriangle = iterate (ap (zipWithLongest 0 0 (+)) (0:)) [1]

我们可以使用(!!) :: [a] -> Int -> a索引列表。但请注意,由于两个原因,这通常是一种反模式:

  1. 查找需要 O(k)时间, k 我们想要获取的索引值;和
  2. 它是一个部分函数,​​因为索引可能超出范围(这里是负索引,而对于有限列表,索引太大)。
  3. 我们知道 Pascal三角形的每一行都包含一个比前一行更多的元素。所以 k -th行包含 k 元素。如果我们想获得每个子列表中的k - 元素,那么我们应该首先忽略所有不具有k个元素的列表。因此,我们使用drop k删除列表的第一个k - 元素,然后使用map (!! k)来获取我们不过滤的每个子列表的k个元素

    所以我们可以编写一个函数:

    kThPascalTriangle :: Num n => Int -> [n]
    kThPascalTriangle k = map (!! k) (drop k pascalTriangle)