Function filterTriples from a list that are not in ascending order - list

I want to implement a function
filterTriples that, given a list of integer triples, removes those that are not in ascending order of size.
Example: filterTriples [(1,2,3), (6,5,4), (6,6,6)] ↝ [(1,2,3), (6,6,6)]. I would like to use list comprehension to implement the function.
I wrote a function which generates such triplets.
My current code is below.
Generating the list of triples:
filterTriplets :: Int -> [(Int, Int, Int)]
filterTriplets n = [(a, b, c) | a <- [1..n], b <- [1..n], c <- [1..n], a<=b && b<=c]
But now I have a list of triplets and I want to filter out those triplets from a list that are not in ascending order of size. I've been searching for identical problems on StackOverflow, but sadly couldn't find anything that I could use.
How to solve this problem?

First of all you need to define a function with signature which accepts collection of triplets and returns a collection of triplets:
filterTriplets :: [(Int, Int, Int)] -> [(Int, Int, Int)]
And implementation using standard functions can look like:
filterTriplets = filter (\(a,b,c) -> a <= b && b <= c)
Using list comprehensions:
filterTriplets x = [(a, b, c) | (a, b, c) <- x, a <= b , b <= c]

Related

Function to find number of occurrences in list

So I already have a function that finds the number of occurrences in a list using maps.
occur :: [a] -> Map a a
occur xs = fromListWith (+) [(x, 1) | x <- xs]
For example if a list [1,1,2,3,3] is inputted, the code will output [(1,2),(2,1),(3,2)], and for a list [1,2,1,1] the output would be [(1,3),(2,1)].
I was wondering if there's any way I can change this function to use foldr instead to eliminate the use of maps.
You can make use of foldr where the accumulator is a list of key-value pairs. Each "step" we look if the list already contains a 2-tuple for the given element. If that is the case, we increment the corresponding value. If the item x does not yet exists, we add (x, 1) to that list.
Our function thus will look like:
occur :: Eq => [a] -> [(a, Int)]
occur = foldr incMap []
where incMap thus takes an item x and a list of 2-tuples. We can make use of recursion here to update the "map" with:
incMap :: Eq a => a -> [(a, Int)] -> [(a, Int)]
incMap x = go
where go [] = [(x, 1)]
go (y2#(y, ny): ys)
| x == y = … : ys
| otherwise = y2 : …
where I leave implementing the … parts as an exercise.
This algorithm is not very efficient, since it takes O(n) to increment the map with n the number of 2-tuples in the map. You can also implement incrementing the Map for the given item by using insertWith :: Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a, which is more efficient.

Create List by multiplying object with [1..n]

I am still not into Haskell and need a hint for the following function.
I want to create a list by adding each multiplication of a pair:
all :: Int -> (Int,Int) -> [(Int, Int)]
all n, pair = ...
E.g. n = 3, pair (1,2) => [(1,2), (2,4), (3,6)]
which expands to [(1*(1,2)), ((2*(1,2)), (3*(1,2))]
I know its something with x <- [1..n] and x*pair but I don't know which built-in function is right to put it together!
You need to do the multiplication separately on the elements in the tuples, and then recreate a tuple. You can use fst and snd to get the elements.
all n pair = [(x*(fst pair), x*(snd pair)) | x <- [1..n]]
Pattern matching is another common way to access tuple elements.
all n (a, b) = [(x*a, x*b) | x <- [1..n]]

haskell: how to get list of numbers which are higher then their neighbours in a starting list

I am trying to learn Haskell and I want to solve one task. I have a list of Integers and I need to add them to another list if they are bigger then both of their neighbors. For Example:
I have a starting list of [0,1,5,2,3,7,8,4] and I need to print out a list which is [5, 8]
This is the code I came up but it returns an empty list:
largest :: [Integer]->[Integer]
largest n
| head n > head (tail n) = head n : largest (tail n)
| otherwise = largest (tail n)
I would solve this as outlined by Thomas M. DuBuisson. Since we want the ends of the list to "count", we'll add negative infinities to each end before creating triples. The monoid-extras package provides a suitable type for this.
import Data.Monoid.Inf
pad :: [a] -> [NegInf a]
pad xs = [negInfty] ++ map negFinite xs ++ [negInfty]
triples :: [a] -> [(a, a, a)]
triples (x:rest#(y:z:_)) = (x,y,z) : triples rest
triples _ = []
isBig :: Ord a => (a,a,a) -> Bool
isBig (x,y,z) = y > x && y > z
scnd :: (a, b, c) -> b
scnd (a, b, c) = b
finites :: [Inf p a] -> [a]
finites xs = [x | Finite x <- xs]
largest :: Ord a => [a] -> [a]
largest = id
. finites
. map scnd
. filter isBig
. triples
. pad
It seems to be working appropriately; in ghci:
> largest [0,1,5,2,3,7,8,4]
[5,8]
> largest [10,1,10]
[10,10]
> largest [3]
[3]
> largest []
[]
You might also consider merging finites, map scnd, and filter isBig in a single list comprehension (then eliminating the definitions of finites, scnd, and isBig):
largest :: Ord a => [a] -> [a]
largest xs = [x | (a, b#(Finite x), c) <- triples (pad xs), a < b, c < b]
But I like the decomposed version better; the finites, scnd, and isBig functions may turn out to be useful elsewhere in your development, especially if you plan to build a few variants of this for different needs.
One thing you might try is lookahead. (Thomas M. DuBuisson suggested a different one that will also work if you handle the final one or two elements correctly.) Since it sounds like this is a problem you want to solve on your own as a learning exercise, I’ll write a skeleton that you can take as a starting-point if you want:
largest :: [Integer] -> [Integer]
largest [] = _
largest [x] = _ -- What should this return?
largest [x1,x2] | x1 > x2 = _
| x1 < x2 = _
| otherwise = _
largest [x1,x2,x3] | x2 > x1 && x2 > x3 = _
| x3 > x2 = _
| otherwise = _
largest (x1:x2:x3:xs) | x2 > x1 && x2 > x3 = _
| otherwise = _
We need the special case of [x1,x2,x3] in addition to (x1:x2:x3:[]) because, according to the clarification in your comment, largest [3,3,2] should return []. but largest [3,2] should return [3]. Therefore, the final three elements require special handling and cannot simply recurse on the final two.
If you also want the result to include the head of the list if it is greater than the second element, you’d make this a helper function and your largest would be something like largest (x1:x2:xs) = (if x1>x2 then [x1] else []) ++ largest' (x1:x2:xs). That is, you want some special handling for the first elements of the original list, which you don’t want to apply to all the sublists when you recurse.
As suggested in the comments, one approach would be to first group the list into tuples of length 3 using Preludes zip3 and tail:
*Main> let xs = [0,1,5,2,3,7,8,4]
*Main> zip3 xs (tail xs) (tail (tail xs))
[(0,1,5),(1,5,2),(5,2,3),(2,3,7),(3,7,8),(7,8,4)]
Which is of type: [a] -> [b] -> [c] -> [(a, b, c)] and [a] -> [a] respectively.
Next you need to find a way to filter out the tuples where the middle element is bigger than the first and last element. One way would be to use Preludes filter function:
*Main> let xs = [(0,1,5),(1,5,2),(5,2,3),(2,3,7),(3,7,8),(7,8,4)]
*Main> filter (\(a, b, c) -> b > a && b > c) xs
[(1,5,2),(7,8,4)]
Which is of type: (a -> Bool) -> [a] -> [a]. This filters out elements of a list based on a Boolean returned from the predicate passed.
Now for the final part, you need to extract the middle element from the filtered tuples above. You can do this easily with Preludes map function:
*Main> let xs = [(1,5,2),(7,8,4)]
*Main> map (\(_, x, _) -> x) xs
[5,8]
Which is of type: (a -> b) -> [a] -> [b]. This function maps elements from a list of type a to b.
The above code stitched together would look like this:
largest :: (Ord a) => [a] -> [a]
largest xs = map (\(_, x, _) -> x) $ filter (\(a, b, c) -> b > a && b > c) $ zip3 xs (tail xs) (tail (tail xs))
Note here I used typeclass Ord, since the above code needs to compare with > and <. It's fine to keep it as Integer here though.

How to compare elements in a [[]]?

I am dealing with small program with Haskell. Probably the answer is really simple but I try and get no result.
So one of the part in my program is the list:
first = [(3,3),(4,6),(7,7),(5,43),(9,9),(32,1),(43,43) ..]
and according to that list I want to make new one with element that are equal in the () =:
result = [3,7,9,43, ..]
Even though you appear to have not made the most minimal amount of effort to solve this question by yourself, I will give you the answer because it is so trivial and because Haskell is a great language.
Create a function with this signature:
findIdentical :: [(Int, Int)] -> [Int]
It takes a list of tuples and returns a list of ints.
Implement it like this:
findIdentical [] = []
findIdentical ((a,b) : xs)
| a == b = a : (findIdentical xs)
| otherwise = findIdentical xs
As you can see, findIdentical is a recursive function that compares a tuple for equality between both items, and then adds it to the result list if there is found equality.
You can do this for instance with list comprehension. We iterate over every tuple f,s) in first, so we write (f,s) <- first in the right side of the list comprehension, and need to filter on the fact that f and s are equal, so f == s. In that case we add f (or s) to the result. So:
result = [ f | (f,s) <- first, f == s ]
We can turn this into a function that takes as input a list of 2-tuples [(a,a)], and compares these two elements, and returns a list [a]:
f :: Eq a => [(a,a)] -> [a]
f dat = [f | (f,s) <- dat, f == s ]
An easy way to do this is to use the Prelude's filter function, which has the type definition:
filter :: (a -> Bool) -> [a] -> [a]
All you need to do is supply predicate on how to filter the elements in the list, and the list to filter. You can accomplish this easily below:
filterList :: (Eq a) => [(a, a)] -> [a]
filterList xs = [x | (x, y) <- filter (\(a, b) -> a == b) xs]
Which behaves as expected:
*Main> filterList [(3,3),(4,6),(7,7),(5,43),(9,9),(32,1),(43,43)]
[3,7,9,43]

Generate a list from another function which returns a Bool in Haskell

i'm currently working on lists of lists (which we use to represent a grid).
I have one function which receive 2 arguments (my grid and a tuple of 4 Integers) and it returns a Boolean.
Now with a new function, I need to generate a list of every tuples which returns True for a certain grid. For exemple, function1 (1,3,2,2) grid1 will return True so I need to get (1,3,2,2) in my list.
The other problem is that I have multiple conditions to respect for my tuple (a,b,c,d) of 4 Integers such as : 1 <= a < a+c <= n and 1 <= b < b+d <= m where n is the number of lines (so length grid) and m is the number of columns (so length (head grid)).
I had the idea to use map but so far I never used it in such a situation and everything I tried failed.
Thanks
There are two basic approaches for doing this in Haskell.
Generate a stream of tuples that satisfy the constaints you listed but don't necessarily return true according to the function
Use filter to par down the list
Or we can try to avoid generating all that redundant data and just have something like
Use our knowledge of the predicate to only generate a stream of valid tuples in the first place
Since we're working with an arbitrary function, we can't really do the second so we'll opt for the former. Thus we start by generating all of the tuples satisfying the constaints 1 <= a < a + c <= n and 1 <= b < b + d <= m.
Now it's clear that a is in the range [1 .. n] and b is in [1 .. m]. Furthermore, for each a we can have c in [a + 1 .. n - a] and for each b we can have [b + 1 .. m - b]. We'll use Haskell's list comprehensions to encode this is a very snazzy way
allTuples :: Int -> Int -> [(Int, Int, Int, Int)]
allTuples n m = -- First we take in n, m
[(a, b, c, d) |
a <- [1 .. n],
b <- [1 .. m],
c <- [a + 1 .. n - a],
d <- [b + 1 .. m - b]]
Here these <- will do the right thing and take all possible combinations. Next all we need do is use filter to remove elements.
prune :: Grid -> [(Int, Int, Int, Int)] -> [(Int, Int, Int, Int)]
prune grid tuples = filter (\t -> f grid t) tuples
-- could have written:
-- prune grid = filter (f grid)
-- prune = filter . f
Then we can glue them together, but I'll leave this final step to you because I'm not sure how you'll use it in your application. You can also merge these steps into a single list comprehension:
allTuples :: Int -> Int -> [(Int, Int, Int, Int)]
allTuples n m = -- First we take in n, m
[(a, b, c, d) |
a <- [1 .. n],
b <- [1 .. m],
c <- [a + 1 .. n - a],
d <- [b + 1 .. m - b],
f grid (a, b, c, d)]