Related
I am trying to code a function that returns the element that appears the most in a list. So far I have the following
task :: Eq a => [a] -> a
task xs = (map ((\l#(x:xs) -> (x,length l)) (occur (sort xs))))
occur is a function that takes a list and returns a list of pairs with the elements of the inputted list along with the amount of times they appear. So for example for a list [1,1,2,3,3] the output would be [(1,2),(2,1),(3,2)].
However, I am getting some errors related to the arguments of map. Can anyone tell me what I'm doing wrong?
A map maps every item to another item, so here \l is a 2-tuple, like (1,2), (2, 1) or (3, 2). It thus does not make much sense to work with length l, since length :: Foldable f => f a -> Int will always return one for a 2-tuple: this is because only the second part of the 2-tuple is used in the foldable. But we do not need length in the first place.
What you need is a function that can retrieve the maximum based on the second item of the 2-tuple. We can make use of the maximumOn :: Ord b => (a -> b) -> [a] -> a from the exta package, or we can implement our own function to calculate the maximum on a list of items.
Such function thus should look like:
maximumSnd :: Ord b => [(a, b)] -> (a, b)
maximumSnd [] = error "Empty list"
maximumSnd (x:xs) = go xs x
where go [] m = m
go (x#(xa, xb):xs) (ya, yb)
| xb > yb = go … … -- (1)
| otherwise = go … … -- (2)
Here (1) should be implemented such that we make a recursive call but work with x as the new maximum we found thus far. (2) should make a recursive call with the same thus far maximum.
Once we have implemented the maxSnd function, we can use this function as a helper function for:
task :: Eq a => [a] -> (a, Int)
task xs = maxSnd (occur xs)
or we can use fst :: (a, b) -> a to retrieve the first item of the 2-tuple:
task :: Eq a => [a] -> a
task xs = (fst . maxSnd) (occur xs)
In case there are two characters with a maximum number of elements, the maximumSnd will return the first one in the list of occurrences.
I need to sort an integer list on haskell, from smaller to greater numbers, but i dont know where to start.
The recursion syntax is kinda difficult for me
A little bit of help would be great.
Ive done this but it does not solve my problem:
ordenarMemoria :: [Int] -> [Int]
ordenarMemoria [] = []
ordenarMemoria (x:y:xs)
| y > x = ordenarMemoria (y:xs)
| otherwise = ordenarMemoria (x:xs)
Thanks
You attempt is on the right track for a bubble sort, which is a good starting place for sorting. A few notes:
You handle the cases when the list is empty or has at least two elements (x and y), but you have forgotten the case when your list has exactly one element. You will always reach this case because you are calling your function recursively on smaller lists.
ordenarMemoria [x] = -- how do you sort a 1-element list?
Second note: in this pattern
ordenarMemoria (x:y:xs)
| y > x = ordenarMemoria (y:xs)
| otherwise = ordenarMemoria (x:xs)
you are sorting a list starting with two elements x and y. You compare x to y, and then sort the rest of the list after removing one of the two elements. This is all good.
The question I have is: what happened to the other element? A sorted list has to have all the same elements as the input, so you should use both x and y in the output. So in:
| y > x = ordenarMemoria (y:xs)
you have forgotten about x. Consider
| y > x = x : ordenarMemoria (y:xs)
which indicates to output x, then the sorted remainder.
The other branch forgets about one of the inputs, too.
After you fix the function, you might notice that the list gets a bit more sorted, but it is still not completely sorted. That's a property of the bubble sort—you might have to run it multiple times.
I'll highly recommend you read Learn You a Haskell, there is an online version here, it has a chapter where you can learn how to sort lists using recursion, like Quicksort for example:
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let smallerSorted = quicksort [a | a <- xs, a <= x]
biggerSorted = quicksort [a | a <- xs, a > x]
in smallerSorted ++ [x] ++ biggerSorted
I need to sort an integer list
How about sort from Data.List?
$ stack ghci
Prelude> :m + Data.List
Prelude Data.List> sort [2,3,1]
[1,2,3]
There are lots of choices. I generally recommend starting with bottom-up mergesort in Haskell, but heapsort isn't a bad choice either. Quicksort poses much more serious difficulties.
-- Given two lists, each of which is in increasing
-- order, produce a list in increasing order.
--
-- merge [1,4,5] [2,4,7] = [1,2,4,4,5,7]
merge :: Ord a => [a] -> [a] -> [a]
merge [] ys = ???
merge xs [] = ???
merge (x : xs) (y : ys)
| x <= y = ???
| otherwise = ???
-- Turn a list of elements into a list of lists
-- of elements, each of which has only one element.
--
-- splatter [1,2,3] = [[1], [2], [3]]
splatter :: [a] -> [[a]]
splatter = map ????
-- Given a list of sorted lists, merge the adjacent pairs of lists.
-- mergePairs [[1,3],[2,4],[0,8],[1,2],[5,7]]
-- = [[1,2,3,4],[0,1,2,8],[5,7]]
mergePairs :: Ord a => [[a]] -> [[a]]
mergePairs [] = ????
mergePairs [as] = ????
mergePairs (as : bs : more) = ????
-- Given a list of lists of sorted lists, merge them all
-- together into one list.
--
-- mergeToOne [[1,4],[2,3]] = [1,2,3,4]
mergeToOne :: Ord a => [[a]] -> [a]
mergeToOne [] = ???
mergeToOne [as] = ???
mergeToOne lots = ??? -- use mergePairs here
mergeSort :: Ord a => [a] -> [a]
mergeSort as = ???? -- Use splatter and mergeToOne
Once you've filled in the blanks above, try optimizing the sort by making splatter produce sorted lists of two or perhaps three elements instead of singletons.
Here is a modified either quicksort or insertion sort. It uses the fastest method of prefixing or suffixing values to the output list. If the next value is less than or greater than the first or last of the list, it is simply affixed to the beginning or end of the list. If the value is not less than the head value or greater than the last value then it must be inserted. The insertion is the same logic as the so-called quicksort above.
Now, the kicker. This function is made to run as a foldr function just to reduce the complexity of the the function. It can easily be converted to a recursive function but it runs fine with foldr.
f2x :: (Ord a) => a -> [a] -> [a]
f2x n ls
| null ls = [n]
| ( n <= (head ls) ) = n:ls -- ++[11]
| ( n >= (last ls) ) = ls ++ [n] -- ++ [22]
| True = [lx|lx <-ls,n > lx]++ n:[lx|lx <-ls,n < lx]
The comments after two line can be removed and the function can be run with scanr to see how many hits are with simple prefix or suffix of values and which are inserted somewhere other that the first or last value.
foldr f2x [] [5,4,3,2,1,0,9,8,7,6]
Or af = foldr a2x [] ... af [5,4,3,2,1,0,9,8,7,6] >-> [0,1,2,3,4,5,6,7,8,9]
EDIT 5/18/2018
The best thing about Stack Overflow is the people like #dfeuer that make you think. #dfeuer suggested using partition. I am like a child, not knowing how. I expressed my difficulty with partition but #dfeuer forced me to see how to use it. #dfeuer also pointed out that the use of last in the above function was wasteful. I did not know that, either.
The following function uses partition imported from Data.List.
partition outputs a tuple pair. This function is also meant to use with foldr. It is a complete insertion sort function.
ft nv ls = b++[nv]++e where (b,e) = partition (<=nv) ls
Use it like above
foldr ft [] [5,4,3,2,1,0,9,8,7,6]
Haskell and functional programming is all about using existing functions in other functions.
putEleInSortedListA :: Ord a => a -> [a] -> [a]
putEleInSortedListA a [] = [a]
putEleInSortedListA a (b:bs)
| a < b = a : b : bs
| otherwise = b: putEleInSortedListA a bs
sortListA :: Ord a => [a] -> [a]
sortListA la = foldr (\a b -> putEleInSortedListA a b) [] la
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]
I have been working with Haskell for a little over a week now so I am practicing some functions that might be useful for something. I want to compare two lists recursively. When the first list appears in the second list, I simply want to return the index at where the list starts to match. The index would begin at 0. Here is an example of what I want to execute for clarification:
subList [1,2,3] [4,4,1,2,3,5,6]
the result should be 2
I have attempted to code it:
subList :: [a] -> [a] -> a
subList [] = []
subList (x:xs) = x + 1 (subList xs)
subList xs = [ y:zs | (y,ys) <- select xs, zs <- subList ys]
where select [] = []
select (x:xs) = x
I am receiving an "error on input" and I cannot figure out why my syntax is not working. Any suggestions?
Let's first look at the function signature. You want to take in two lists whose contents can be compared for equality and return an index like so
subList :: Eq a => [a] -> [a] -> Int
So now we go through pattern matching on the arguments. First off, when the second list is empty then there is nothing we can do, so we'll return -1 as an error condition
subList _ [] = -1
Then we look at the recursive step
subList as xxs#(x:xs)
| all (uncurry (==)) $ zip as xxs = 0
| otherwise = 1 + subList as xs
You should be familiar with the guard syntax I've used, although you may not be familiar with the # syntax. Essentially it means that xxs is just a sub-in for if we had used (x:xs).
You may not be familiar with all, uncurry, and possibly zip so let me elaborate on those more. zip has the function signature zip :: [a] -> [b] -> [(a,b)], so it takes two lists and pairs up their elements (and if one list is longer than the other, it just chops off the excess). uncurry is weird so lets just look at (uncurry (==)), its signature is (uncurry (==)) :: Eq a => (a, a) -> Bool, it essentially checks if both the first and second element in the pair are equal. Finally, all will walk over the list and see if the first and second of each pair is equal and return true if that is the case.
Say I have any list like this:
[4,5,6,7,1,2,3,4,5,6,1,2]
I need a Haskell function that will transform this list into a list of lists which are composed of the segments of the original list which form a series in ascending order. So the result should look like this:
[[4,5,6,7],[1,2,3,4,5,6],[1,2]]
Any suggestions?
You can do this by resorting to manual recursion, but I like to believe Haskell is a more evolved language. Let's see if we can develop a solution that uses existing recursion strategies. First some preliminaries.
{-# LANGUAGE NoMonomorphismRestriction #-}
-- because who wants to write type signatures, amirite?
import Data.List.Split -- from package split on Hackage
Step one is to observe that we want to split the list based on a criteria that looks at two elements of the list at once. So we'll need a new list with elements representing a "previous" and "next" value. There's a very standard trick for this:
previousAndNext xs = zip xs (drop 1 xs)
However, for our purposes, this won't quite work: this function always outputs a list that's shorter than the input, and we will always want a list of the same length as the input (and in particular we want some output even when the input is a list of length one). So we'll modify the standard trick just a bit with a "null terminator".
pan xs = zip xs (map Just (drop 1 xs) ++ [Nothing])
Now we're going to look through this list for places where the previous element is bigger than the next element (or the next element doesn't exist). Let's write a predicate that does that check.
bigger (x, y) = maybe False (x >) y
Now let's write the function that actually does the split. Our "delimiters" will be values that satisfy bigger; and we never want to throw them away, so let's keep them.
ascendingTuples = split . keepDelimsR $ whenElt bigger
The final step is just to throw together the bit that constructs the tuples, the bit that splits the tuples, and a last bit of munging to throw away the bits of the tuples we don't care about:
ascending = map (map fst) . ascendingTuples . pan
Let's try it out in ghci:
*Main> ascending [4,5,6,7,1,2,3,4,5,6,1,2]
[[4,5,6,7],[1,2,3,4,5,6],[1,2]]
*Main> ascending [7,6..1]
[[7],[6],[5],[4],[3],[2],[1]]
*Main> ascending []
[[]]
*Main> ascending [1]
[[1]]
P.S. In the current release of split, keepDelimsR is slightly stricter than it needs to be, and as a result ascending currently doesn't work with infinite lists. I've submitted a patch that makes it lazier, though.
ascend :: Ord a => [a] -> [[a]]
ascend xs = foldr f [] xs
where
f a [] = [[a]]
f a xs'#(y:ys) | a < head y = (a:y):ys
| otherwise = [a]:xs'
In ghci
*Main> ascend [4,5,6,7,1,2,3,4,5,6,1,2]
[[4,5,6,7],[1,2,3,4,5,6],[1,2]]
This problem is a natural fit for a paramorphism-based solution. Having (as defined in that post)
para :: (a -> [a] -> b -> b) -> b -> [a] -> b
foldr :: (a -> b -> b) -> b -> [a] -> b
para c n (x : xs) = c x xs (para c n xs)
foldr c n (x : xs) = c x (foldr c n xs)
para c n [] = n
foldr c n [] = n
we can write
partition_asc xs = para c [] xs where
c x (y:_) ~(a:b) | x<y = (x:a):b
c x _ r = [x]:r
Trivial, since the abstraction fits.
BTW they have two kinds of map in Common Lisp - mapcar
(processing elements of an input list one by one)
and maplist (processing "tails" of a list). With this idea we get
import Data.List (tails)
partition_asc2 xs = foldr c [] . init . tails $ xs where
c (x:y:_) ~(a:b) | x<y = (x:a):b
c (x:_) r = [x]:r
Lazy patterns in both versions make it work with infinite input lists
in a productive manner (as first shown in Daniel Fischer's answer).
update 2020-05-08: not so trivial after all. Both head . head . partition_asc $ [4] ++ undefined and the same for partition_asc2 fail with *** Exception: Prelude.undefined. The combining function g forces the next element y prematurely. It needs to be more carefully written to be productive right away before ever looking at the next element, as e.g. for the second version,
partition_asc2' xs = foldr c [] . init . tails $ xs where
c (x:ys) r#(~(a:b)) = (x:g):gs
where
(g,gs) | not (null ys)
&& x < head ys = (a,b)
| otherwise = ([],r)
(again, as first shown in Daniel's answer).
You can use a right fold to break up the list at down-steps:
foldr foo [] xs
where
foo x yss = (x:zs) : ws
where
(zs, ws) = case yss of
(ys#(y:_)) : rest
| x < y -> (ys,rest)
| otherwise -> ([],yss)
_ -> ([],[])
(It's a bit complicated in order to have the combining function lazy in the second argument, so that it works well for infinite lists too.)
One other way of approaching this task (which, in fact lays the fundamentals of a very efficient sorting algorithm) is using the Continuation Passing Style a.k.a CPS which, in this particular case applied to folding from right; foldr.
As is, this answer would only chunk up the ascending chunks however, it would be nice to chunk up the descending ones at the same time... preferably in reverse order all in O(n) which would leave us with only binary merging of the obtained chunks for a perfectly sorted output. Yet that's another answer for another question.
chunks :: Ord a => [a] -> [[a]]
chunks xs = foldr go return xs $ []
where
go :: Ord a => a -> ([a] -> [[a]]) -> ([a] -> [[a]])
go c f = \ps -> let (r:rs) = f [c]
in case ps of
[] -> r:rs
[p] -> if c > p then (p:r):rs else [p]:(r:rs)
*Main> chunks [4,5,6,7,1,2,3,4,5,6,1,2]
[[4,5,6,7],[1,2,3,4,5,6],[1,2]]
*Main> chunks [4,5,6,7,1,2,3,4,5,4,3,2,6,1,2]
[[4,5,6,7],[1,2,3,4,5],[4],[3],[2,6],[1,2]]
In the above code c stands for current and p is for previous and again, remember we are folding from right so previous, is actually the next item to process.