I'm new to Haskell and I really need some help!
I have to write a program that includes a recursive function to produce a list of binomial coefficients for the power n=12 using the Pascal's triangle technique.
I have some ideas in my head but because I'm just getting started I have no idea how to implement this to haskell?!
Could someone please help me out??
first row: (a+b)^0 = 1
second row: (a+b)^1 = 1a+1b
third row: (a+b)^2 = 1a^2+2ab+1b^2
and so on...this is my main idea. But I cant even try this out because I have no idea how I put this in Haskell..getting errors all the time
Start by assigning an index to each element in the triangle:
| 0 1 2 3 4 5 6
--+--------------------------
0 | 1
1 | 1 1
2 | 1 2 1
3 | 1 3 3 1
4 | 1 4 6 4 1
5 | 1 5 10 10 5 1
6 | 1 6 15 20 15 6 1
Here I've simply put the triangle on its side so that we can number them. So here I'd say that the element at (6, 4) is 15, whereas (4, 6) doesn't exist. Now focus on writing a function
pascal :: Integer -> Integer -> Integer
pascal x y = ???
Such that you can generate this version of the triangle. You can start by writing
pascal x y
| x == 0 = 1
| x == y = 1
| x < y = error "Not a valid coordinate for Pascal's triangle."
| otherwise = pascal ? ? + pascal ? ?
Note that here, instead of figuring out which elements should be added together by diagonals, you can do it via rectangular coordinates. Here, you'll note that y is which row in the triangle you're on and x is the position of the element in that row. All you need to do is figure out what goes in place of the ?s.
Once you get that working, I've got a one-liner for this triangle that is more efficient and can generate the entire triangle all at once while still using recursion:
import Data.List (scanl1)
pascals :: [[Integer]]
pascals = repeat 1 : map (scanl1 (+)) pascals
Don't try turning this solution in to your professor, it's not what they're looking for and it would make it pretty obvious someone gave you this solution if you've only been doing Haskell for a week. However, it really shows how powerful Haskell can be for this sort of problem. I would show how to index pascals to get a given (n, k) value, but doing so would also give you too many hints for solving the naive recursion.
Since there's been some confusion, the reason why I gave this solution is to draw a parallel between it and the often shown lazy implementation for the Fibonacci sequence:
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
Compared to
fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
This definition generates an infinite list of all the Fibonacci numbers, and does so quite efficiently (from the point of view of the CPU, RAM is a different story). It encodes in its first 2 elements the base case, then a recursive expression that can calculate the rest. For the Fibonaccis, you need 2 values to start you off, but for Pascal's triangle, you only need one value, that value just happens to be an infinite list. There is an easy to see pattern going across the columns in the grid I posted above, the scanl1 (+) function just takes advantage of this pattern and allows us to generate it very easily, but this is generating the diagonals of the triangle rather than the rows. To get the rows, you can index this list, or you can do some fancy tricks with take, drop, and other such functions, but that's an exercise for another day.
Start out with the triangle itself:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
...
You should notice that to write down the next row, you must apply this rule: sum the previous rows' adjacent elements, using a 0 for the lonely edge elements. Visually:
0 1 0
\+/ \+/
0 1 1 0
\+/ \+/ \+/
0 1 2 1 0
\+/ \+/ \+/ \+/
1 3 3 1
...
Operationally, that looks like this:
For row 0:
[1] (it's a given; i.e. base case)
For row 1:
[0, 1] <- row 0 with a zero prepended ([0] ++ row 0)
+ +
[1, 0] <- row 0 with a zero appended (row 0 ++ [0])
= =
[1, 1] <- element-wise addition
For row 2:
[0, 1, 1]
+ + +
[1, 1, 0]
= = =
[1, 2, 1]
Generally, for row N:
element-wise addition of:
[0] ++ row(N-1)
row(N-1) ++ [0]
Remember that element-wise addition of lists in Haskell is zipWith (+).
Thus we arrive at the following Haskell definition:
pascal 0 = [1]
pascal n = zipWith (+) ([0] ++ pascal (n-1)) (pascal (n-1) ++ [0])
Or in a fashion similar to the famous "lazy fibs":
pascals = [1] : map (\xs -> zipWith (+) ([0] ++ xs) (xs ++ [0])) pascals
Another possible solution (more suitable for beginners in my opinion):
pascal :: Integer -> [Integer]
pascal 0 = [1]
pascal 1 = [1, 1]
pascal n = let p = pascal (n - 1)
in [1] ++ pascalStep p ++ [1]
pascalStep :: [Integer] -> [Integer]
pascalStep [] = []
pascalStep [_] = []
pascalStep (x:y:xs) = x + y : pascalStep (y : xs)
Using let to avoid more space usage.
pascal is calling recursively to find all previous rows, using them to get the next row, until getting to the desired row.
Output:
*Main> pascal 3
[1,3,3,1]
*Main> pascal 4
[1,4,6,4,1]
*Main> pascal 5
[1,5,10,10,5,1]
Start with the base case.
pascal 0 0 = 1
Then handle the edge cases
pascal n 0 = 1
pascal n r | n == r = 1
Now expand with the recursive step
pascal n r = pascal (n - 1) (r - 1) + pascal (n - 1) r
If you want the list for a specific row, write a wrapper
binom n = map (pascal n) [0..n]
Figuring out the types shouldn't be hard
pascal :: Integral a => a -> a -> a
binom :: Integral a => a -> [a]
I'm on my phone so please excuse the mistakes, but you can use Haskell's lazy evaluation in a really cool way here.
pascals :: [[Int]]
pascals = [1]:map (\r -> zipWith (+) (0:r) (r++[0])) pascals
Which you could make point free with a fork but it's rather esoteric.
pascals :: [[Int]]
pascals = [1]:map ((zipWith (+) -<) (0:) (++[0])) pascals
But I personally really like this code, and thinks it's worth being readable-
pascals :: [[Int]]
pascals = [1]:map next pascals
where next = (zipWith (+) -<) (0:) (++[0])
But combinators like that can get a bit confusing, no matter how much I like point free programming.
Related
I have been trying to implement a list of Fibonacci number sequence from 0 to n without using the lazy zipwith method. What I have so far is code that returns a list from n to 1. Is there any way I can change this code so it returns the list from 0-n at all?
Example:
fib_seq 4 = [3,2,1,1]
-- output wanted: [1,1,2,3]
If there is not a way to do what I want the code to do, is there a way to just return the list of Fibonacci numbers taking in a number say again 4 it would return [0, 1, 1, 2].
fib_seq :: Int -> [Int]
fib_seq 0 = [0]
fib_seq 1 = [1]
fib_seq n = sum (take 2 (fib_seq (n-1))) : fib_seq (n-1)
Another way you could choose to implement the fib numbers is the use of a helper function then a function on it's own that will produce the infinite list of fib numbers, or you could use take 10 fibs and the output for this would be the first 10 fib numbers. My function is definitely not the fastest way to work out the fib numbers infintely that would be with the zipWith function, but you are not using that here so here is my way to implement it without zipWith.
for example take 10 fibs would return: [0,1,1,2,3,5,8,13,21,34]
fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
fibs :: [Int]
fibs = (map fib [0..])
It is often the case that you can solve a problem by considering a slightly more general version of it.
Say we want the infinite Fibonacci list starting with two prescribed initial values a and b. There is an obvious recursive solution:
$ ghci
GHCi, version 8.8.4: https://www.haskell.org/ghc/ :? for help
...
λ>
λ> aux_fib a b = a : (aux_fib b (a+b))
λ>
λ> take 4 (aux_fib 1 1)
[1,1,2,3]
λ>
And so:
λ>
λ> fib_seq n = take n (aux_fib 1 1)
λ>
λ> fib_seq 4
[1,1,2,3]
λ>
Note: camel case is regarded as more idiomatic in Haskell, so it would be more like auxFib and fibSeq.
If you wanted to have the list start from 0 you could use a helper function and then use this helper function within your fib_seq (which i recommend you change to Camel case so like fibSeq, standard haskell notation)
Ok so the functions as follow fibSeq 7 would return [0,1,1,2,3,5,8]:
fibHelp :: Int -> Int -> [Int]
fibHelp x y = x : (fibHelp y (x+y))
fibSeq :: Int -> [Int]
fibSeq n = take n (fibHelp 0 1)
It feels a bit like cheating, but you could use the closed formula for the Fibonacci sequence like this:
fib n = (phi^n - psi^n) / sqrt 5
where
phi = (1 + sqrt 5) / 2
psi = (1 - sqrt 5) / 2
fibSeq n = fib <$> [1 .. n]
Otherwise the Haskell Wiki has many more implementation variants to chose from. For example very succinctly
fibs = 0 : 1 : next fibs
where
next (a : t#(b:_)) = (a+b) : next t
Haskell allows to represent recurrent functions in a very concise way. For example, infinite list, that contains Fibonacci numbers can be defined as follows:
fibs :: [Integer]
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
I am dealing with 'probabilists' Hermite polynomials, which have the following recursion relation:
What would be the optimal way to construct the infinite list of n-th Hermite polynomials for given x?
We can write it as:
hermite :: (Enum n, Num n) => n -> [n]
hermite x = s
where s#(_:ts) = 1 : x : zipWith3 (\hn2 hn1 n1 -> x*hn1 - n1*hn2) s ts [1..]
where the first items 1 : x : ... are the first elements of the hermite (you can fill in other values).
For the next one, we zip the original values s (so that starts with H0), the tail ts of s (that starts with H1) and the index (that starts with 2, 3, ...) and perform an operation x*hn1 - x*hn2 (nh1 stands for Hn-1, and nh2 stands for Hn-2), and so we calculate the next element each time.
The first 11 values for x = 0.75 are:
Prelude> take 11 (hermite 0.75)
[1.0,0.75,-0.4375,-1.828125,-5.859375e-2,7.2685546875,5.744384765625,-39.30303955078125,-69.68797302246094,262.1583366394043,823.8105096817017]
So the first value is 1, the second x, the third one x*x-2, the fourth one x*x*x-2*x-3*x, and so on.
That being said, if I recall correctly, the recursion formula of the Hermite polynomials is:
Hn(x) = 2×x×Hn-1(x)-2×(n-1)Hn-2(x)
instead of the one quoted in the question.
In that case the formula is thus:
hermite :: (Enum n, Num n) => n -> [n]
hermite x = s
where s#(_:ts) = 1 : 2 * x : zipWith3 helper s ts [1..]
helper hn2 hn1 n1 = 2 * (x * hn1 - n1 * hn2)
Then the first 11 values are:
Prelude> take 11 (hermite 0.75)
[1.0,1.5,0.25,-5.625,-9.9375,30.09375,144.515625,-144.3515625,-2239.74609375,-1049.994140625,38740.4384765625]
Which is correct acording to this Wolfram article:
H0 = 1
H1 = 2*x
H2 = 4˙x2 - 2
H3 = 8˙x3 - 4˙x
H4 = 16˙x4 - 48˙x2 + 12
Which maps exactly on the values we obtained:
Prelude> let x = 0.75 in [1,2*x,4*x*x-2,8*x*x*x-4*x,16*x*x*x*x-48*x*x+12]
[1.0,1.5,0.25,0.375,-9.9375]
I have written the following Fibonacci play program as part of learning Haskell:
fibonacci 0 = [0]
fibonacci 1 = [0,1]
fibonacci n = let
foo'1 = last (fibonacci (n-1))
foo'2 = last (fibonacci (n-2))
in reverse((foo'1 + foo'2):reverse (fibonacci (n-1)))
The program works:
ghci>fibonacci 6
[0,1,1,2,3,5,8]
But, the performance goes down exponentially with n. If I give it an argument of 30 it takes about a minute to run as opposed to running instantaneously at 6. It seems the lazy execution is burning me and fibonacci is getting run once for every element in the final list.
Am I doing something silly or missing something?
(I already got rid of the ++ thinking that might be doing it)
As pointed out in the comments, your approach is a tad overcomplicated. In particular, you don't need to use recursive calls, or even the reverse function, in order to generate the Fibonacci sequence.
A linear-time implementation
In addition to your own answer, here is a textbook one-liner, which uses memoization:
fibs :: [Integer]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
Once you have fibs, writing your fib function is trivial:
fib :: Int -> [Integer]
fib n
| n < 0 = error "fib: negative argument"
| otherwise = take (n+1) fibs
This implementation of fib has complexity Θ(n), which is obviously much better than Θ(exp(n)).
Test in GHCi
λ> :set +s
λ> fib 6
[0,1,1,2,3,5,8]
(0.02 secs, 7282592 bytes)
λ> fib 30
[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418,317811,514229,832040]
(0.01 secs, 1035344 bytes)
As you can see, fib 30 is evaluated in well under one minute on my machine.
Further reading
For a much more comprehensive treatment of how to generate the Fibonacci sequence in Haskell, I refer you to this haskell.org wiki
Here is the answer to the question using #icktoofay's pointer to memoization. The answer included a function that quickly returned a given fibonacci number, so I used their example to create a solution to my original problem--creating a list of the Fibonacci numbers up to the requested number.
This solution runs pretty much instantaneously (the page has the additional benefit of referring to my approach as "naive")
memoized_fib :: Int -> Integer
memoized_fib = (map fib [0 ..] !!)
where fib 0 = 0
fib 1 = 1
fib n = memoized_fib (n-2) + memoized_fib (n-1)
fib 0 = [0]
fib 1 = [0,1]
fib n = reverse ((memoized_fib (n-2) + memoized_fib(n-1)) : reverse (fib (n-1)))
You don't need to add memoization to your function - it already has all the previous results, producing a list as it does. You just need to stop ignoring those results, as you do right now using last.
First of all, if it's more natural to build the list in reverse order, there's no reason not to:
revFib 0 = [0]
revFib 1 = [1,0]
revFib n | n > 0 = let f1 = head (revFib (n-1))
f2 = head (revFib (n-2))
in f1 + f2 : revFib (n-1)
This is still slow, as we're still ignoring all the previous results except the very last one, situated at the head of the list. We can stop doing that,
revFib 0 = [0]
revFib 1 = [1,0]
revFib n | n > 0 = let f1 = head (revFib (n-1))
f2 = head (tail (revFib (n-1)))
in f1 + f2 : revFib (n-1)
and then we'll name the common subexpression, so that it is shared among its uses, and is only calculated once:
revFib 0 = [0]
revFib 1 = [1,0]
revFib n | n > 0 = let prevs = revFib (n-1)
[f1,f2] = take 2 prevs
in f1 + f2 : prevs
and suddenly it's linear instead of exponential.
I'm new to Haskell, and I like its graceful grammar. But I haven't found a suitable way to define an infinite 2D array -- for example, the Pascal Triangle:
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 ...
...
I know how to define a simple function:
pascal :: Int -> Int -> Int
pascal 1 _ = 1
pascal _ 1 = 1
pascal x y = (pascal (x - 1) y) + (pascal x (y - 1))
Since Haskell do not memorize function values, a call to pascal 20 20 will take a long time. How could I define a fast version (like an infinite 2D array)?
You can create the pascal triangle as an infinite, lazy, nested list
pascal :: [[Integer]]
pascal = repeat 1 : map (scanl1 (+)) pascal
The above definition is a bit terse but what it essentially means is just that each row is an accumulating sum of the previous row, starting from repeat 1 i.e. an infinite list of ones. This has the advantage that we can calculate each value in the triangle directly without doing any O(n) indexing.
Now you can index the list to find the value you need, e.g.
> pascal !! 19 !! 19
35345263800
The list will only get partially evaluated for the values you need.
You can also easily output a range of values:
> 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
Another option is to use your original function but memoize it using one of the various memorization libraries available. For example, using 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))
The obvious choice for an infinite 2D "array" would be a nested list, i.e. an infinite list of infinite lists. It might thus be
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)
This now has the function calls memoised. It's still not optimal because of list O (n) access, but not that bad either.
fibs :: [Int]
fibs = 0 : 1 : [ a + b | (a, b) <- zip fibs (tail fibs)]
This generates the Fibonacci sequence.
I understand the behaviour of the guards, of :, zip and tail, but I don't understand <-. What is it doing here?
Due to the upvotes I made my comment into an answer.
What you see is not a guard but it is list comprehension. For starters think of it as a way to express a mathematical set notation like A = { x | x element N } which means something along the lines of: The set A is the set of all natural numbers. In list comprehension that would be [x | x <- [1..] ].
You can also use constraints on your numbers: [x | x <- [1..], x `mod` 2 == 0 ] and many other things.
There are alot of good haskell turorials out there that cover list comprehension and even a StackOverflow question regarding haskell resources.
The only tricky thing is the zip fibs (tail fibs). zip just makes a pairwise list from each of its arguments. So if you have two lists like this:
[ 1, 2, 3, 4 ]
[ "a", "b", "c", "d" ]
Zipping them will make:
[ (1,"a"), (2,"b"), (3,"c"), (4,"d") ]
The left arrow (assignment into a destructuring pattern) just extracts the paired elements so they can be added together. The two lists being zipped are fibs and (tail fibs) -- in other words, the Fibonacci sequence, and the Fibonacci sequence offset by 1 element. Haskell is lazily-evaluated, so it can calculate the list to however many elements are required. This applies to zip as well.
One advantage of functional programming is that you can evaluate an expression by hand like it is a math problem:
fibs = 0 : 1 : [ a + b | (a, b) <- zip fibs (tail fibs)]
= 0 : 1 : [ a + b | (a, b) <- zip [0, 1, ??] (tail [0, 1, ??])]
Here the ?? is the part which has not yet been evaluated. We will fill it in as we proceed.
= 0 : 1 : [ a + b | (a, b) <- zip [0, 1, ??] [1, ??])]
= 0 : 1 : [ a + b | (a, b) <- (0, 1) : zip [1, ??] [??]]
Note that I am eliding the evaluation of zip since its definition is not given here and the details are not really germane to the current question. This is the notation I will use to show each pair of numbers is created by zip and consumed by the list comprehension.
= 0 : 1 : 0+1 : [ a + b | (a, b) <- zip [1, ??] [??]]
= 0 : 1 : 1 : [ a + b | (a, b) <- zip [1, ??] [??]]
Now we know that the next element in the ?? is a 1:
= 0 : 1 : 1 : [ a + b | (a, b) <- zip [1, 1, ??] [1, ??]]
= 0 : 1 : 1 : [ a + b | (a, b) <- (1, 1) : zip [1, ??] [??]]
= 0 : 1 : 1 : 1+1 : [ a + b | (a, b) <- zip [1, ??] [??]]
= 0 : 1 : 1 : 2 : [ a + b | (a, b) <- zip [1, ??] [??]]
And the next element is a 2:
= 0 : 1 : 1 : 2 : [ a + b | (a, b) <- zip [1, 2, ??] [2, ??]]
Rinse and repeat.
Let's expand it out.
zip creates pairs out of the contents of two lists. So the first pair zip fibs (tail fibs) gives us is (0, 1), which adds up to 1. So now the list is [0,1,1]. We now know three elements in the list, so the list comprehension can continue, grabbing the next item from the list and the next item from the tail, which gives (1,1) — added together, making 2. Then we get the next pair, which is (1,2), making the next number in the sequence 3. This can continue infinitely, since the comprehension will always provide enough items.
For what it's worth, I find the following version easier to understand:
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
The list comprehension in the brackets:
[ a + b | (a, b) <- zip fibs (tail fibs)]
returns a list containing the output (a + b) where the variables a and b come from the result of
zip fibs (tail fibs)
The key concept here is lazy evaluation which means that if the value is right there then take it without further computing say that i have got the value and the job is done, i don't need to compute future value temporary now. and if the value is not available then just compute it and of course it's lazy so it won't bother computing next needed value.
i write another implementation to illustrate this and use ?? to be a value placeholder which needs to be computed if needed.
fibs = 1:1:[ y!!1 + y!!0 | x<-[2..], y <- [[last (take x fibs), last (take (x-1) fibs)]] ]
i use x to indicate number of available values in fibs (which doesn't need to be computed again) and y to be a [[last fib values]] nested list. its inner list contains last two values of available values in fibs.
so here is the process of the computation:
x == 2, so y is [last (take 2 fibs), last (take 1 fibs)]. lazy evaluation lets us just take available values and don't bother worrying values in the future. it tells me to take first 2 and 1 values of fibs and the values are right there 1,1 and 1. y now is [last [1,1], last [1]] which is [1,1] and to get final value it need to compute y!!1 + y!!0. That's obvious and final value is 2. so now fibs is [1, 1, 2, ??].
x == 3, just the same as step 1. y is [last [take 3 fibs], last [take 2 fibs]] which is [last [1,1,2], last [1,1]], the value now is available so we can just take it and go on. Finally, we got the fourth value 3.
that's it, just repeat the above steps and you can get all values even it is infinite
Doesn't it seems familiar? just like using a recursive function to compute fibs. we now let compiler itself to do the stuff(referring). we use the lazy evaluation here.
the zip implementation is just another representation of [last fibs values] here. you just need a little modification to understand the zip version of fibs implementation.
haskell wiki: lazy evaluation
for <- symbol: List comprehension
I prefer the more general
fib = 1 : [ x + y | (x, y) <- zip fib (0 : fib) ]
This most closely models how one understands the Fibonacci sequence in terms of generating functions. If f(n) = 0 for n < 0, f(0) = 1, and f(n) = a*f(n-1) + b*f(n-2) for n > 0, then we'd like to be able to write the single line
f(n) = 1_0 + a*f(n-1) + b*f(n-2)
and have the reader know what we mean. Unfortunately, this requires some unstated conventions to make sense.
Using the generating function g(t) = f(0) + f(1)t + f(2)t^2 + ... we can write the equation
g(t) = 1 + a t g(t) + b t^2 g(t)
which easily solves for g(t) in closed form as
g(t) = 1 / (1 - a t - b t^2)
The Haskell code
g = 1 : [ a*x + b*y | (x, y) <- zip g (0 : g) ]
implements this same equation.
It defines this stream diagram,(*)
.---->>---->>----.
/ \
<---- 0 <---- 1 ----<<--- (+)
\ /
*--->>---*
that pulls new input from itself as it is produced, but always by one and two positions behind the production point, maintaining the two "back pointers" into the sequence as it were, one position apart.
This is reflected in the definition,
-- .------->>------>>---.
-- / \
fibs = 0 : 1 : [ a + b | a <- fibs
{- \ -} | b <- tail fibs]
-- \ /
-- *-->>------>>---*
with parallel list comprehensions (:set -XParallelListComp etc.).
Since it only uses its last two elements, it is equivalent to
map fst . iterate (\(a, b) -> (b, a+b)) $ (0,1)
(*) The execution of this diagram proceeds as follows:
.---->>---->>----.
/ \ 0
? <---- 0 <---- 1 ----<<--- (+)
\ / 1
*--->>---*
.---->>---->>----.
/ \ 1
0,? <---- 1 <---- 1 ----<<--- (+)
\ / 1
*--->>---*
.---->>---->>----.
/ \ 1
0,1,? <---- 1 <---- 2 ----<<--- (+)
\ / 2
*--->>---*
.--->>---->>----.
/ \ 2
0,1,1,? <--- 2 <--- 3 ----<<--- (+)
\ / 3
*--->>---*
.--->>--->>---.
/ \ 3
0,1,1,2,? <--- 3 <-- 5 ---<<--- (+)
\ / 5
*--->>---*
......