Ordering an Ordered list Function in Haskell - list

for my coursework I have to take two lists of numbers, sort them and then combine them and output the new list in order, this works if the lists are already in order as they are typed but not if say a 9 is at the start of a first list so the trouble I'm having is sorting the list after it's combined, in other languages I'd do this with a for loop, but not sure in Haskell
here the code I have:
merge :: Ord a => [a] -> [a] -> [a]
merge x [] = x
merge [] x = x
merge (x:xs) (y:ys) = if x < y
then x:(merge xs (y:ys))
else y:(merge (x:xs) ys)

It sounds like what you're actually supposed to implement is merge sort.
In merge sort you merge two sorted list to get one sorted list, yes. The missing observation is that a list of size 0 or 1 is necessarily already sorted.
This means that if you start applying your function to lists that are of size 0 or 1, then merge the results of that merge, then merge the result of that, eventually you will end up with a fully sorted list.
Here's an example:
-- Your function
merge :: Ord a => [a] -> [a] -> [a]
merge x [] = x
merge [] x = x
merge (x:xs) (y:ys) = if x < y
then x:(merge xs (y:ys))
else y:(merge (x:xs) ys)
-- Arbitrarily split a list into two ~equally sized smaller lists.
-- e.g. [2,7,1,8,2] -> ([2,7,1], [8,2])
split list = splitAt ((length list) `div` 2) list
-- Split a list into halves until each piece is size 0 or 1,
-- then 'merge' them back together.
mergeSort [] = []
mergeSort [x] = [x]
mergeSort list =
let (firstHalf, secondHalf) = split list
in merge (mergeSort firstHalf) (mergeSort secondHalf)
mergeSort [2,7,1,8,2] will evaluate to [1,2,2,7,8]. Using only your merge function, the list has been sorted.

So your current solution will return a sorted list if both input lists are sorted. If the input lists aren't sorted, you've got 2 options, sort the input lists individually, then merge them as you are already, or merge them unsorted, and sort the new list.
It seems more reasonable to merge unsorted lists and then sort them as one, so here is the solution. I've used a quick implementation of quicksort, but you could use whatever sorting algorithm you wish.
--takes 2 sorted or unsorted lists, merges them, then sorts them
merge :: (Ord a) => [a] -> [a] -> [a]
merge [] [] = []
merge x [] = sort x
merge [] y = sort y
merge x y = sort (x ++ y)
-- where first element of list is pivot
sort :: (Ord a) => [a] -> [a]
sort [] = []
sort (x:xs) = sort [x'|x'<-xs, x'<=x] ++ [x] ++ sort [x'|x'<-xs, x'>x]
There are many ways to do this, and this way has the downside of having to resort the list even if the lists were already sorted. You could get around this by checking if lists are sorted, then sorting them if needed. I hope this answer helps.

For a problem like merge sort, you want to divide-and-conquer so that your input lists are always ordered. One way to do this by breaking the input down into singletons, which are always ordered by definition, then making your merge function tail-recursively insert whichever of the two list heads is smaller. When one input list is finally empty, it appends the other.

Related

Using foldr on a list of infinite lists

I am trying to write a function in Haskell, that does the following:
You input a list of integers, for these integers, using map, there is a function applied to them that returns an infinite list of these integers. Then, I want to apply foldr to the list of lists, using union, so that the result will be the union of those lists in the list.
Now the problem is that when I do for example take 10 'function' [1,2], it will first calculate the infinite list for 1, and because it is an infinite list, it will never do this for 2. So then it returns only the first 10 elements of this infinite list of the first elements in the input list, with union applied to it, which is just the same list.
My question is: is there a way to create the infinite lists for all the elements in the input list at the same time, so that when I do take 10 'function' [1,2] for example, it will return the first 10 elements of the union of the infinite lists for 1 and 2.
(I don't know the number of elements in the input list)
This is my code, to make it clearer:
pow :: Integer -> [Integer]
pow n = map (^n) [1, 2..]
function :: [Integer] -> [Integer]
function xs = foldr union [] (map pow xs)
The union function works on arbitrary lists and removes duplicates, so it must first evaluate one of its arguments completely before it can continue with the other argument.
I think you want to explicitly introduce the assumption that your lists are sorted, then you can write an efficient function that merges (like the merge in a merge sort) the input lists and computes the union without needing to evaluate one of the lists before the other.
I don't know if such a merge function exists in a library, but you can pretty easily define it yourself:
-- | Computes the union of two sorted lists
merge :: Ord a => [a] -> [a] -> [a]
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys)
| x <= y = x : merge (dropWhile (== x) xs) (dropWhile (== x) (y:ys))
| otherwise = y : merge (x:xs) (dropWhile (== y) ys)
Then your original fold with this new merge function should behave as desired:
ghci> pow n = map (^n) [1..]
ghci> function xs = foldr merge [] (map pow xs)
ghci> take 10 (function [2,3])
[1,4,8,9,16,25,27,36,49,64]
If you intend the input and output lists to be sorted, check out data-ordlist. If you just want all the elements but don't care what order, try concat . transpose.

Sort algorithm for list of integers in Haskell with recursion

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

Fast length of an intersection with duplicates in Haskell

I'm writing a mastermind solver, and in an inner loop I calculate the length of the intersection with duplicates of two lists. Right now the function I have is
overlap :: Eq c => [c] -> [c] -> Int
overlap [] _ = 0
overlap (x:xs) ys
| x `elem` ys = 1 + overlap xs (delete x ys)
| otherwise = overlap xs ys
Is it possible to make this faster? If it helps, the arguments to overlap are short lists of the same length, at most 6 elements, and the c type has less than 10 possible values.
In general it is (almost) impossible to boost the performance of such algorithm: in order to remove duplicates in two unordered and unhashable lists, can be done in O(n^2).
In general, you can however boost performance with the following conditions (per condition, a different approach):
If you can for instance ensure that for each list you create/modify/..., the order of the elements is maintained; this can require some engineering. In that case, the algorithm can run in O(n).
In that case you can run it with:
--Use this only if xs and ys are sorted
overlap :: Ord c => [c] -> [c] -> Int
overlap (x:xs) (y:ys) | x < y = overlap xs (y:ys)
| x > y = overlap (x:xs) ys
| otherwise = 1 + overlap xs ys
overlap [] _ = 0
overlap _ [] = 0
In general sorting of a list can be done in O(n log n) and is thus more efficient than your O(n^2) overlap algorithm. The new overlap algorithm runs in O(n).
In case c is ordered, you might use a Data.Set as well. In that case you can use the fromList method that runs in O(n log n) to create a TreeSet for the two lists, then use the intersection function to calculate the intersection in O(n) time and finally use the size function to calculate the size.
--Use this only if c can be ordered
overlap :: Ord c => [c] -> [c] -> Int
overlap xs ys = size $ intersection (fromList xs) (fromList ys)
Are you using same ys for multiple xs?
If yes, you can try to calculate hash values for each element in ys and match by this value, but keep in mind that calculating hash needs to be faster then 6 comparisons.
If either of those is Ord you may also sort it earlier, and verify only necessary part of ys.
However, if you need fast random access lists aren't the best structure, you should probably take a look at Data.Array and Data.HashMap

Haskell, pulling both lists from a tuple of lists

I'm making a "merge sort" using 2 helper functions. The first helper function splits the lists into a tuple of lists putting odd and even indexes in the separate lists.
Example: [1,2,3,4,5,6]
Returns: ([1,3,5],[2,4,6])
The second helper function assumes that the lists are sorted and merges them.
I'm to implement a merge sort of an unsorted list using these 2 functions.
I have this terribly inefficient piece that essentially splits (length - 1) * 2 times and merges the list (length - 1) times.
sort length (z:zs)
| length == 0 = (z:zs)
| otherwise = sort (length - 1) (merge (fst (split(z:zs))) (snd (split(z:zs)))
I'm calling split twice to get the same info that was done on the first split, and I'm not recursing far enough (where each list is just a singleton and then merge them all).
How can I recurse to the singleton case and pull out both elements of the tuple at the same time?
Thank you in advance for any help you can offer.
You can use uncurry to convert merge to an un-curried function and pass split(z:zs) as argument:
sort (length - 1) $ uncurry merge $ split (z:zs)
The uncurry function transforms function of type a -> b -> c into functions of type (a, b) -> c. In your case merge has type [a] -> [a] -> [a] while uncurry merge has type ([a], [a]) -> [a] and ([a], [a]) is the return type of split.
Alternatively you can simply use a let or a where clause to refer to the result of split:
let (left, right) = split (z:zs)
in sort (length - 1) $ merge left right
which is an improved version of:
let res = split (z:zs)
in sort (length - 1) $ merge (fst res) (snd res)
As a side note your sort function is incorrect. Your definition is like:
sort length (z:zs) = ...
however this matches only non-empty lists. It's also pretty useless to consider the case length == 0 when it can never occurr.
Your definition of sort outght to consider the empty case too:
sort _ [] = []
sort length (z:zs) = ...

How can I write a function in Haskell that takes a list of Ints and returns all the contiguous sublists of that list?

The function needs to take an ordered list of integer elements and return all the combinations of adjacent elements in the original list. e.g [1,2,3] would return [[1,2,3],[1],[1,2],[2],[2,3],[3]].
Note that [1,3] should not be included, as 1 and 3 are not adjacent in the original list.
Apart from the fact that inits and tails aren't found in Prelude, you can define your function as such:
yourFunction :: [a] -> [[a]]
yourFunction = filter (not . null) . concat . map inits . tails
This is what it does, step by step:
tails gives all versions of a list with zero or more starting elements removed: tails [1,2,3] == [[1,2,3],[2,3],[3],[]]
map inits applies inits to every list given by tails, and does exactly the opposite: it gives all versions of a list with zero or more ending elements removed: inits [1,2,3] == [[],[1],[1,2],[1,2,3]]
I hope you already know concat: it applies (++) where you see (:) in a list: concat [[1,2],[3],[],[4]] == [1,2,3,4]. You need this, because after map inits . tails, you end up with a list of lists of lists, while you want a list of lists.
filter (not . null) removes the empty lists from the result. There will be more than one (unless you use the function on the empty list).
You could also use concatMap inits instead of concat . map inits, which does exactly the same thing. It usually also performs better.
Edit: you can define this with Prelude-only functions as such:
yourFunction = concatMap inits . tails
where inits = takeWhile (not . null) . iterate init
tails = takeWhile (not . null) . iterate tail
So, if you need consecutive and non empty answers (as you've noticed in comment).
At first, let's define a simple sublist function.
sublist' [] = [[]]
sublist' (x:xs) = sublist' xs ++ map (x:) (sublist' xs)
It returns all sublists with empty and non-consecutive lists. So we need to filtering elements of that list. Something like sublists = (filter consecutive) . filter (/= []) . sublist'
To check list for it's consecution we need to get pairs of neighbors (compactByN 2) and check them.
compactByN :: Int -> [a] -> [[a]]
compactByN _ [] = [[]]
compactByN n list | length list == n = [list]
compactByN n list#(x:xs)= take n list : compactByN n xs
And finally
consecutive :: [Int] -> Bool
consecutive [_] = True
consecutive x = all (\[x,y] -> (x + 1 == y)) $ compact_by_n 2 x
And we have
λ> sublists [1,2,3]
[[3],[2],[2,3],[1],[1,2],[1,2,3]]
Done. http://hpaste.org/53965
Unless, I'm mistaken, you're just asking for the superset of the numbers.
The code is fairly self explanatory - our superset is recursively built by building the superset of the tail twice, once with our current head in it, and once without, and then combining them together and with a list containing our head.
superset xs = []:(superset' xs) -- remember the empty list
superset' (x:xs) = [x]:(map (x:) (superset' xs)) ++ superset' xs
superset' [] = []