Hello studying Haskell I came up at an exercise at the web that it requested to create a list given an integer the way described below:
for example if integer was 3 then a list should be generated that it contains the following:
[[3],[1,2],[2,1],[1,1,1]]
note
3=3
1+2=3
2+1=3
1+1+1=3
if integer was 2 then it would be:
[[2],[1,1]]
I cannot think a way of implementing this, so can you provide me with any hints? I believe that I must use list comprehension but I cannot think anything further than this
Always start with a type signature:
sums :: Int -> [[Int]]
Now, let's think about the recursion.
What is the base case? Can you think of a number for which the answer is trivial?
Let's say you've implemented your function and it works for all numbers under 10, so sums 9 for example returns the right answer. How would you implement sums 10?
Don't bother yourself with implementation details (e.g. List comprehension vs. filter and map) until you've answered these questions.
And another tip: Haskell programmers love to show off and create tiny-pointfree functions, but don't let it confuse you. Getting things to work is the important thing. It's better to have a working yet somewhat "ugly" solution than to stare at the screen looking for an elegant one.
Good luck!
Looks a bit like partitioning a list. A bit of googling turns up this
http://www.haskell.org/pipermail/beginners/2011-April/006832.html
partitions [] = [[]]
partitions (x:xs) = [[x]:p | p <- partitions xs]
++ [(x:ys):yss | (ys:yss) <- partitions xs]
which produces something like this
*Main> partitions "abc"
[["a","b","c"],["a","bc"],["ab","c"],["abc"]]
now all you have to do is get the length of the inner lists
map (map length) (partitions "abc")
[[1,1,1],[1,2],[2,1],[3]]
you can also change partitions to give you the result directly
partitions' 0 = [[]]
partitions' n = [1:p | p <- partitions' (n-1)]
++ [(1+ys):yss | (ys:yss) <- partitions' (n-1)]
Related
Haskell noob here: I'm still trying to understand the mechanics of the language, so if my question is plain stupid, forgive me and point me to some link which I can learn from (I've searched awhile in similar topics here on stackoverflow, but still I can't get this).
I came out with this function:
chunks :: Int -> [a] -> [[a]]
chunks n xs
| length xs <= n = [xs]
| otherwise = let (ch, rest) = splitAt n xs in ch:chunks n rest
so that
ghci> chunks 4 "abracadabra"
["abra","cada","bra"]
ghci>
ghci> chunks 3 [1..6]
[[1,2,3],[4,5,6]]
I was pretty satisfied with that, then I thought "there's lazy evaluation! I can use this even on an infinite sequence!". So i tried take 4 $ chunks 3 [1..]. I was hoping that the lazy haskell magic would have produced [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]], instead it seems like this time lazyness can't help me: it can't reach the end of the computation (is it walking all the way long to the end of [1..]?)
I think the problem is in the "length xs" part: ghci seems to get stuck also on a simple length [1..]. So I'm asking: is length actually iterating the whole list to give a response? If so, I guess length is to be avoided every time I try to implement something working well with the lazy evaluation, so there is some alternative?
(for instance, how can I improve my example to work with infinite lists?)
is length actually iterating the whole list to give a response?
Yes.
I guess length is to be avoided every time I try to implement something working well with the lazy evaluation
Not just that, it also gives you bad runtimes when laziness isn't a factor (being O(n) in cases where an O(1) check often suffices1), so you should avoid it most of the time in general.
how can I improve my example to work with infinite lists?
You don't need to check whether the length of the list is less than n, you just need to check whether it's zero. And that you can do with a simple pattern match.
1 For example something like f xs | length xs >= 2 = ..., which is O(n), can be replaced with f (x1 : x2 : xs) = ..., which is O(1).
Another trick you can do (which I've seen in Data.Text, but am surprised is not in Prelude for lists in general) is to make length short-circuit as soon as possible by returning an Ordering rather than a Bool.
compareLength :: [a] -> Int -> Ordering
compareLength [] n = compare 0 n
compareLength _ 0 = GT
compareLength (x : xs) n = compareLength xs (n - 1)
Then you can use it in chunks.
chunks :: Int -> [a] -> [[a]]
chunks n xs = case compareLength xs n of
LT -> [xs]
_ -> let (ch, rest) = splitAt n xs in ch:chunks n rest
And this works fine.
*Main> take 4 $ chunks 3 [1..]
[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
For this particular case, other implementations might be more idiomatic, but hopefully this is a nice trick to know.
is length actually iterating the whole list to give a response?
Yes, absolutely.
length is to be avoided every time I try to implement something working well with the lazy evaluation
Yes, absolutely.
so there is some alternative?
Yes: solve the problem without referencing length. There are no general methods of problem solving so you need to work out each specific case.
how can I improve my example to work with infinite lists
You are a railroad worker. A huge train if cars begins where you are standing and stretches over the horizon. You have no idea where it ends, if ever. Your job is to separate it into small trains of three cars each. How do you proceed?
For instance, in the form of something like this:
let f = [ a | a <- [1..], a == a - 1]
I'm just curious. It seems like it'd be possible, but I can't quite wrap my head around how it would work. This question is meant more for understanding how Haskell works, not so much because I'm looking for a practical application.
Also, I know that similar questions have been asked, but none of the posts I looked at offered any help in doing it they way I'm curious about.
Edit: sorry for the vagueness. Let me clarify a new rule, then. The challenge is to find a way to represent an infinite list of fibonacci numbers using as little extra from the first chapter of Learn You A Haskell For Great Good! as possible. How's that? In other words, what's the most creative way you can think of to produce those numbers with as little 'knowledge' as possible. Sorry for making anyones answer invalid, now.
Try this:
import Data.List (tails)
fib :: [Integer]
fib = 0 : 1 : [ a + b | (a:b:_) <- tails fib ]
Yes it makes use of the cons operator (:) for the seed values. However I believe that can be pardoned.
It is certainly possible with a nasty trick: there's a closed form of the Fibonacci sequence
fn = (φn - ψn) / √5
so
Prelude> let (φ, ψ) = (1/2+s, 1/2-s) where s = sqrt(5/4)
Prelude> let fibs = [ round $ (φ^n - ψ^n) / sqrt 5 | n <- [0..] ]
Prelude> take 20 fibs
[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181]
This works in floating point, so it's extremely fast but fails to work exactly at high values:
Prelude> take 3 $ drop 80 fibs
[23416728348467676,37889062373143896,61305790721611584]
Prelude> 23416728348467676 + 37889062373143896 - 61305790721611584
-12
I think it can not work without exploiting irrational numbers or putting some recursion in the comprehension, because list comprehensions are just syntactic sugar for monadic binds and those by themselves aren't Turing-complete, so they can't generate an infinite sequence constructively.
The simplest is of course:
fibs = f 0 1 where f a b = a : (f b (a+b))
We arrive at this solution from the definition.
Let f a b computes a stream of numbers starting with a and followed by b. Then we can use f to compute the substream of numbers following b, if we can compute the number following immediately after b. We know that immediately after b follows a+b, so we get that stream and append it to a.
This solution does not involve any list library functions, using list comprehensions instead.
fib = [ x | (x,_) <- l ]
where l = (0,1) : [ (b,a+b) | (a,b) <- l ]
I am trying to write haskell function that takes list of lists and find the lowest value of all the high values.
So the function takes the list [[1,1,3],[2,5],[1]] and return 1 because its the lowest of 3,5,1.
What haskell function can I use?
Using list comprehension :
maxi xxs = minimum [ maximum a | a <- xxs]
(I'm a beginner in Haskell ... and coding. It's the first time that I figure it out an answer arround here. So, Gratzz to me!! :P )
Data.List contains useful functions,
:browse Data.List
in ghci.
(Looks a lot like homework, so...)
Think "step by step": First you need find all maximums of the individual lists, e.g.:
map maximum [[1,1,3],[2,5],[1]]
--[3,5,1]
Then you need the minimum of this list. So one solution would be:
minOfMax xs = minimum (map maximum xs)
Of course you can also write your own recursive solution, or use a fold:
minOfMax (x:xs) = foldl f (maximum x) xs where
f a bs = min a (maximum bs)
You probably know about project Euler question 5: get the smallest number divisble by all numbers 1 to 20.
The logic I applied was "start with the first number greater than the largest of the list(20) and also divisible by it which is 40" and stepsize of 20 (largest number)
I did this using list comprehension but it's pretty lame.
pe5 = head [x|x<-[40,60..],x`mod`3==0,x`mod`4==0,x`mod`6==0,x`mod`7==0,x`mod`8==0,x`mod`9==0,x`mod`11==0,x`mod`12==0,x`mod`13==0,x`mod`14==0,x`mod`15==0,x`mod`16==0,x`mod`17==0,x`mod`18==0,x`mod`19==0]
Can we do this better perhaps using zipWith and filter maybe?
Just to clarify, this is not a homework assignment. I'm doing this to wrap my brain around Haskell. (So far I'm losing!)
:Thanx all
I think this is a saner way (there may be thousand more better ways but this would suffice) to do it
listlcm'::(Integral a)=> [a] -> a
listlcm' [x] = x
listlcm' (x:xs) = lcm x (listlcm' xs)
In this particular case, you can get it for free using foldl and lcm:
euler = foldl lcm 2 [3..20]
This gives me 232792560 instantaneously.
Since the spoiler has already been posted, I thought I'd explain how it works.
The smallest number divisible by two numbers is also known as the least common multiple of those numbers. There is a function for calculating this in the Prelude.
λ> lcm 10 12
60
Now, to extend this to multiple numbers we exploit the following property
lcm(a1, ... an) = lcm(lcm(a1, ... an-1), an)
In Haskell, f(f(... f(a1, a2), ...), an) can be written foldl1 f [a1, a2, ... an], so we can solve the problem with this simple one-liner:
λ> foldl1 lcm [1..20]
232792560
This finds the solution in a fraction of a second.
Yes, you can do much better. For starters, rewrite to something like
head [x | x<-[40,60..], all (\y -> x`mod`y == 0) [2..20] ]
But what you really need here is not slicker Haskell, but a smarter algorithm. Hint: use the Fundamental Theorem of Arithmetic. Your Haskell solution would then start with the standard sieve-of-Eratosthenes example.
Since this is a exercise in learning Haskell, I will only point out that there is a more efficient way to solve this problem mathematically but I will let you figure that out on your own. Instead, let's solve the problem in Haskell using your logic.
I simplified it a little bit:
head [x | x <- [20,40..], length( filter ( \y -> x `mod` y /= 0) [1..20]) == 0]
This creates a filter on the divisors list, and when its length is 0, it means all the divisors divide our x, so that must be our number. This reduces some of the clutter you had in your example. Note that this method is VERY slow; can you think of a better mathematical way to tackle this? Start looking at prime factorizations...
I would like to make a method where I could give it a list of lengths and it would return all combinations of cartesian coordinates up to those lengths. Easier to explain with an example:
cart [2,5]
Prelude> [ [0,0],[0,1],[0,2],[0,3],[0,4],[1,0],[1,1],[1,2],[1,3],[1,4] ]
cart [2,2,2]
Prelude> [ [0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1] ]
A simple list comprehension won't work because I don't know how long the lists are going to be. While I love Haskell's simplicity for many problems, this is one that I could write procedurally (in C or something) in 5 minutes whereas Haskell gives me an aneurysm!
A solution to this specific problem would help me out a lot; I'd also love to hear about your thought processes when tackling stuff like this.
Umm..
cart = sequence . map (enumFromTo 0 . subtract 1)
It's reasonable to expect that a [[a]] -> [[a]] function doing what we expect already exists in the library. So if one is not familiar with sequence, finding it is a simple matter of hoogling it.
Edit: as newacct pointed out:
cart = mapM (enumFromTo 0 . subtract 1)
This can also be found by feeding the previous solution to HLint.
This can be solved recursively. First, the Cartesian product of nothing is {∅}:
cart [] = [[]]
(Or define just the 1-element form if the empty product is invalid:
cart [x] = [[i] | i <- [0 .. x-1]]
)
Then, the Cartesian product of x:xs can be written as
cart (x:xs) = [i:rest | i <- [0 .. x-1], rest <- cart xs]
In general, if you what to write a function f that requires the list's length N, try to think of a way to make f(N) depends on smaller lists e.g. f(N - 1) only, then solve the base case f(0) or f(1) etc. This transforms the problem into a recursion that can be easily solved.
I bet your procedural solution would involve recursion. Our Haskell solution will involve recursion too.
So, recursion. First the recursive case.
cart (c : cs) = [i : r | i <- [0 .. c-1], r <- rcart]
where rcart = cart cs
Here we're just saying that for each possible initial co-ordinate, and each possible combination of cartesian co-ordinates from the remaining lengths, we do the obvious thing of combining the co-ordinate with the remaining co-ordinates.
Then the base case.
cart [] = [[]]
You might think cart [] = []. I did at first. But think about what the recursive case requires from the base case.