Pascal's triangle in Haskell

SICP中考题1.2->1.12是关于Pascal's triangle,如下图所示,初中数学就学过了。

 

 

SICP是以scheme作为讲解语言的,如果用Haskell来写这个Pascal's triangle会怎么样呢?程序会简短很多吗?(至少用C/C++/Java来写的话程序不会短)。

 

 

ft [x] = [x]
ft (x:xs) = (x+(head xs)) : ft xs
loop x 0 = [x]
loop x n = [x]++loop (head x : ft x) (n-1)
triangle1 n = loop [1] n

 

运行结果:

 

*Main> triangle1 6
[[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1],[1,5,10,10,5,1]]

 

上面的haskell代码共5行, 可不可以让代码更紧凑一点呢?loop和ft函数可变为triangle的内部函数,这个SICP中scheme的思想一样。看看改进后的haskell代码:

 

triangle2 n = loop [1] n where
                loop x 1 = [x]
                loop x n = [x]++loop (head x : ft x) (n-1)
                ft [x] = [x]
                ft (x:xs) = (x+(head xs)) : ft xs

 

 好了,现在只有一个triangle函数了,看起来比第一版好一些,但是代码行数没有减少,仍然是5行,还有优化的空间吗?

我们知道haskell是Lazy的functional语言,所以我们还可以对loop进行优化,看看第三版的haskell代码:

 

triangle3 n = take n (loop [1]) where
                loop x = [x]++loop (head x : ft x)
                ft [x] = [x]
                ft (x:xs) = (x+(head xs)) : ft xs

 与第二版比较,第三版中的loop没有判断递归临界条件,那loop岂不变成了死循环了,这就是haskell的lazy特性的,loop的确会产生无限的list,但是我们仅使用前面的n个,所以这里使用take n。

triangle3的代码只有四行,比triangle2少了一行,还可以再减少行数吗?看看第四版的haskell代码:

 

triangle4 n = take n (loop [1]) where
                loop x = [x]++loop (head x : ft x)
                ft (x:xs) = if xs == [] then [x] else (x+(head xs)) : ft xs

 同样我们优化了ft函数,使得ft的临界条件用判断语句加在ft的主题函数中,这样就又少了一行,现在的triangle4仅仅只有3行。

 

haskell由于善于处理这种数学问题,所以用haskell的思维来解决这类问题往往简单明了,相比这下,C/C++/Java则不是太适合来解决这种问题了,用C/C++/Java你是不可能用3行代码就解决Pascal's triangle的。

 

 

 

你可能感兴趣的:(haskell)