Sum all elements with same snd of a list Haskell - list

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.

Related

How can I get multiple nth elements in a list?

I want to know how I can get multiple elements in a list in one function
for example if I wanted to get elements 1 2 3 and 4 from list a, I would have to type a!!0 ++ a!!1 ++ a!!2 ++ a!!3. This takes up a lot of space especially if the list name is more than one character. so I'm wondering if I can do something like a!![0,1,2,3] instead and get all of those elements in a much shorter way. Thank you.
You can work with a mapping where you lookup all items for a list, so:
map (a !!) [0,1,2,3]
If you are however interested in the first four items, you can work with take :: Int -> [a] -> [a]:
take 4 a
especially since looking up by an index (with (!!)) is not a common operation in Haskell: this is unsafe since it is not guaranteed that the index is in bounds. Most list processing is done with functions like take, drop, sum, foldr, etc.

how can I easily get the two biggest elements of an array?

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)

Implementing own Union function without going through lists twice

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

What is the easiest way to add an element to the end of the list?

As:: : 'a -> 'a list -> 'a list is used to add an element to the begin of a list, Could anyone tell me if there is a function to add an element to the end of a list? If not, I guess List.rev (element::(List.rev list)) is the most straightforward way to do it?
Thank you!
The reason there's not a standard function to do this is that appending at the end of a list is an anti-pattern (aka a "snoc list" or a Schlemiel the Painter algorithm). Adding an element at the end of a list requires a full copy of the list. Adding an element at the front of the list requires allocating a single cell—the tail of the new list can just point to the old list.
That said, the most straightforward way to do it is
let append_item lst a = lst # [a]
list#[element] should work. # joins lists.
Given that this operation is linear, you should not use it in the "hot" part of your code, where performance matters. In a cold part, use list # [element] as suggest by Adi. In a hot part, rewrite your algorithm so that you don't need to do that.
The typical way to do it is to accumulate results in the reverse order during processing, and then reverse the whole accumulated list before returning the result. If you have N processing steps (each adding an element to the list), you therefore amortize the linear cost of reverse over N elements, so you keep a linear algorithm instead of a quadratic one.
In some case, another technique that work is to process your elements in reverse order, so that the accumulated results turn out to be in the right order without explicit reversal step.

permutation in haskell

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.