I have a list:
let a = [1, 2, 3]
I need to get another list:
[1, 2, 3] ++ [1*2, 2*3, 1*3] ++ [1*2*3]
It is a product of all possible unique coombinations of list's elements. I have founded permutations in Data.List, but as I see it is something different.
Is there any library functions to get this list or can you give me examles how can I create your own function.
Thanks.
For a library function, you can use subsequences from Data.List:
Prelude Data.List> subsequences [1,2,3]
[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
You can get all of the products using map product $ subsequences [1,2,3].
But that is not in the same order as you specified. So you can sort it,
using sortBy from Data.List and comparing from Data.Ord:
Prelude Data.List Data.Ord> sortBy (comparing length) $ subsequences [1,2,3]
[[],[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
Again, get the products using map product.
Your other idea, to write a function yourself, is
the best idea if you are learning Haskell. Give it a try!
You want all subsequences, not permutations. Permutations give you all possible orders of the same elements. Whereas a subsequence is any sequence that has a subset of elements of the original, in the same order.
In addition to the function mentioned above, there's a clever trick to do this with some other library functions, but I'm not sure how helpful it will be to you.
import Control.Monad (filterM)
subsequences' :: [a] -> [[a]]
subsequences' = filterM $ const [False, True]
This trick takes advantage of the viewpoint of the list monad as modeling non-deterministic calculation. For each element in the list, it's included or not, non-deterministically, regardless of what it is.
It's efficient, and precisely the kind of thing the list monad is designed for, but it's somewhat opaque. You would probably learn more from implementing the same idea directly, based on the descriptions I've provided.
Related
It's not a difficult problem, but I'm not able to find a solution for it without writing 5 lines or more.
I want the definition of the following function:
-- takes a list and give back the 2 biggest elements
getTwoBiggest :: [Int] -> (Int, Int)
Edit
I could do it by sorting and taking the 2 first elements, but I don't find a clear documentation for sorting a list in descending order.
How can I do it ?
What is the connection with the type Down ?
To get a list sorted in reverse order, you should make use of sortBy and and Down.
if you don't know them, you can find their documentation easily via hoogle:
https://hoogle.haskell.org/?hoogle=Down
https://hoogle.haskell.org/?hoogle=sortBy
sortBy lets you specify a custom comparison function.
Down is a newtype wrapper to reverse the sort order - specified by an Ord instance - of the type that it wraps.
Putting those together with a bit of error handling will give you:
import Data.Ord
import Data.List
getTwoBiggest :: [Int] -> (Int, Int)
getTwoBiggest xs | (x:y:_) <- reverseSort xs = (x,y)
| otherwise = undefined -- hande lists with less than two elements
where reverseSort = sortBy (comparing Down)
Given erlang list is L = [[ [], [1,3], [4,5] ]].
Output expected is [[1,3], [4,5]]
I tried with lists:flatten/1 but it returns the flattened list as [1,3,4,5].
This question is ambiguous, as it does not really tell us how flattening needs to be done. Just from your input/output example, it appears you only want to flatten one level and ignore the empty lists. This can be achieved via:
1> lists:filter(fun (X) -> X /= [] end, lists:append([[ [], [1,3], [4,5] ]])).
[[1,3],[4,5]]
But one can imagine other flattenings as well that fit these criteria. Hope this gets you started!
no, flatten function returns a list with elements that are not lists, it eliminates all lists inside the list entered.
if you did an efficient algorithm, you don't need to flatten any list so the best way to create lists is to add elements at the head of list and try to never use the ++ and the -- operators.
I have to write a Union function using recursion
The ouput has to be the Union (no duplicates) of two lists. My teacher said the implementation has to be recursive and we cannot go through the lists twice but I don't think I can come up with a way of solving the problem without going through the lists twice?
My ideas which would solve the problem (but involve going through lists twice):
- Merge then remove duplicates
- Sorting the lists, then merge
Any hints or help would be appreciated
Edit: Well so I got to combine both lists by doing this:
union1 :: (Eq a) => [a] -> [a] -> [a]
union1 xs [] = xs
union1 [] ys = ys
union1 (x:xs)(y:ys) = x:y:union1(xs)(ys)
Then I thought I could use nub or a similar function to remove the duplicates but I got stuck thinking because then I would be going through the lists twice, right?
What is list union?
I would like to first point out that the requirements your teacher gave you are a bit vague. Moreover, union on multisets (aka sets that can have duplicates, like lists) have two different definitions in mathematics (other source). I am no mathematician, but here is what I was able to glean from various internets. Here is one definition:
λ> [1,2,2,3,3,3] `unionA` [1,2,2,2,3] --also called multiset sum
[1,1,2,2,2,2,2,3,3,3,3]
This is simply (++), if you're not worried about ordering. And here is the other:
λ> [1,2,2,3,3,3] `unionB` [1,2,2,2,3]
[1,2,2,2,3,3,3] --picks out the max number of occurrences from each list
Adding to this confusion, Data.List implements a somewhat quirky third type of union, that treats its left input differently from its right input. Here is approximately the documentation found in comments the source code of union from Data.List:
The union function returns the list union of the two lists. Duplicates, and elements of the first list, are removed from the the second list, but if the first list contains duplicates, so will the result. For example,
λ> "dog" `union` "cow"
"dogcw"
Here, you have 3 possible meanings of "union of lists" to choose from. So unless you had example input and output, I don't know which one your teacher wants, but since the goal is probably for you to learn about recursion, read on...
Removing duplicates
Removing duplicates from unordered lists in Haskell can be done in linear time, but solutions involve either random-access data structures, like Arrays, or something called "productive stable unordered discriminators", like in the discrimination package. I don't think that's what your teacher is looking for, since the first is also common in imperative programming, and the second is too complex for a beginner Haskell course. What your teacher probably meant is that you should traverse each list explicitly only once.
So now for the actual code. Here I will show you how to implement union #3, starting from what you wrote, and still traverse the lists (explicitly) only once. You already have the basic recursion scheme, but you don't need to recurse on both lists, since we opted for option #3, and therefore return the first list unchanged.
Actual code
You'll see in the code below that the first list is used as an "accumulator": while recursing on the second list, we check each element for a duplicate in the first list, and if there isn't a duplicate, we append it to the first list.
union [] r = r
union l [] = l
unionR ls (r:rs)
| r `elem` ls = unionR ls rs --discard head of second list if already seen
--`elem` traverses its second argument,
--but see discussion above.
| otherwise = unionR (r:ls) rs --append head of second list
As a side note, you can make this a bit more readable by using a fold:
union xs = foldl step xs where --xs is our first list; no recursion on it,
--we use it right away as the accumulator.
step els x
| x `elem` els = els
| otherwise = x : els
I'm trying to do a polynomial calculator in Haskell and I'm having some problems with the multiplication. The polynomials are introduced as a list of coefficients where the first term corresponds to x^0, the second one corresponds to x^1 and so on.
For the multiplication I have a list of tuples which indicate, on the first element, the coefficient they belong to and, on the second element, they show the corresponding coefficient:
[(0,0),(0,-1),(0,-2),(0,-3),(0,-4),(0,1),(1,0),(2,-1),(3,-2),(4,-3),(0,2),(2,1),(4,0)
(This is done to keep reference to each item multiplied and the coefficient it belongs to)
Since it's one of my first steps into functional programming I'm having some trouble on making a list where the first element is the sum of all the second elements from the tuples on the list shown above with 0 as its first element, the second term should be the sum of all second elemts from the tuples in the list shown above with 1 as its first element, and so on.
I tried with Data.Sequence update as pointed in the first answer here but it doesn't seems to 'update' an already created Data.Sequence, It returns a new one each time.
Is there any way to create a list and update its contents based on index? I'm trying to figure how to solve this problem recursively but I have no idea how to do it so any help would be appreciated.
Here is the solution,
import Data.List
import Data.Function
combine :: [(Int,Int)] -> [Int]
combine = map (sum . map snd) . groupBy ((==) `on` fst) . sort
Read the function from right to left to understand what it is doing.
Here is the breakage into smaller parts to understand it
*Main> sort [(0,0),(0,-1),(0,-2),(0,-3),(0,-4),(0,1),(1,0),(2,-1),(3,-2),(4,-3),(0,2),(2,1),(4,0)]
[(0,-4),(0,-3),(0,-2),(0,-1),(0,0),(0,1),(0,2),(1,0),(2,-1),(2,1),(3,-2),(4,-3),(4,0)]
This sorts the list, so all pairs with same first element are together. After this you can also use a fold.
*Main> groupBy ((==) `on` fst) . sort $ [(0,0),(0,-1),(0,-2),(0,-3),(0,-4),(0,1),(1,0),(2,-1),(3,-2),(4,-3),(0,2),(2,1),(4,0)]
[[(0,-4),(0,-3),(0,-2),(0,-1),(0,0),(0,1),(0,2)],[(1,0)],[(2,-1),(2,1)],[(3,-2)],[(4,-3),(4,0)]]
This combines all the pairs with same first element.
*Main> combine [(0,0),(0,-1),(0,-2),(0,-3),(0,-4),(0,1),(1,0),(2,-1),(3,-2),(4,-3),(0,2),(2,1),(4,0)]
[-7,0,0,-2,-3]
Now we just need to calculate the sum of the second element in the list of lists.
Here we go, bear with me. The over-all goal is to return the max alignment between two lists. If there are more than one alignment with the same length it can just return the first.
With alignment I mean the elements two lists share, in correct order but not necessarily in order. 1,2,3 and 1,2,9,3; here 1,2,3 would be the longest alignment. Any who, know for the predicates that I already have defined.
align(Xs, Ys, [El | T]) :-append(_, [El | T1], Xs),append(_, [El | T2], Ys),align(T1, T2, T).
align(_Xs, _Ys, []).
Then I use the built-in predicate findall to get a a list of all the alignments between these lists? In this case it puts the biggest alignment first, but I'm not sure why.
findall(X,align([1,2,3],[1,2,9,3],X),L).
That would return the following;
L = [[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []].
That is correct, but now I need a predicate that combines these two and returns the biggest list in the list of lists.
Use the solution given in this answer.
You could also try to avoid using findall/3,
because you don't really need to build a list in order to find its largest element.
So you just need to find the largest item in the list?
Edit:
Ok, so a better answer is this:
If you care about performance, then you need to write your own predicate which scans the list keeping track of the largest item.
If you don't carte so much about performance and you just want it to work, you could just reverse sort it and then take the first item in the sorted list. The advantage of this is that by using a sort library predicate you should be able to implement it in a few lines.