Related
given a list of list pairs ::[a,a], I would like to return the possible combinations of lists, where the sublists have been merged on the last of one sublit matching head of the next.
for example
-- combine two lists if they front and back match
merge :: Eq a => [[a]] -> [[a]]
merge (x:y:ys) | last x == head y = merge $ (x ++ (drop 1 y)) : ys
| otherwise = []
merge xs = xs
combinations :: Eq a => [[a]] -> [[a]]
combinations = nub . concatMap merge . permutations
λ= merge [1,2] [2,3]
[1,2,3]
-- there should be no duplicate results
λ= combinations [[1,3],[1,3],[1,3],[1,3],[2,1],[2,1],[2,1],[2,2],[3,2],[3,2],[3,2]]
[[1,3,2,2,1,3,2,1,3,2,1,3],[1,3,2,1,3,2,2,1,3,2,1,3],1,3,2,1,3,2,1,3,2,2,1,3]]
-- the result must be a completely merged list or an empty list
λ= combinations [[1,3], [3,1], [2,2]]
[]
λ= combinations [[1,3], [3, 1]]
[[1,3,1],[3,1,3]]
λ= combinations [[1,3],[3,1],[3,1]]
[[3,1,3,1]]
I can't quite wrap my head around the recursion needed to do this efficiently.
I ended with this solution, but it contains duplicates (you can use Data.List(nub) to get rid of them).
import Data.List(partition)
main :: IO ()
main = do
print $ show tmp
input = [[1,3],[1,3],[1,3],[1,3],[2,1],[2,1],[2,1],[2,2],[3,2],[3,2],[3,2]]
tmp = combinations input
-- this function turns list into list of pair, first element is element of the
-- input list, second element is rest of the list
each :: [a] -> [a] -> [(a, [a])]
each h [] = []
each h (x:xs) = (x, h++xs) : each (x:h) xs
combinations :: (Eq a) => [[a]] -> [[a]]
combinations l = concat $ map combine $ each [] l
where
-- take pair ("prefix list", "unused lists")
combine :: (Eq a) => ([a], [[a]]) -> [[a]]
combine (x, []) = [x]
combine (x, xs) = let
l = last x
-- split unused element to good and bad
(g, b) = partition (\e -> l == head e) xs
s = each [] g
-- add on element to prefix and pass rest (bad + good except used element) to recursion. so it eat one element in each recursive call.
combine' (y, ys) = combine (x ++ tail y, ys ++ b)
-- try to append each good element, concat result
in concat $ map combine' s
I'm not sure if I fully understand what you want to do, so here are just a few notes and hints.
given a list of list pairs ::[a,a]
(...) for example
λ= merge [1,2] [2,3]
Firstly those are not lists of pairs, each element of the list is an integer not a pair. They just happen to be lists with two elements. So you can say they are of type [Int] or an instance of type [a].
the sublists have been merged on the last of one sublit matching head of the next.
This suggests that the size of the lists will grow, and that you will constantly need to inspect their first and last elements. Inspecting the last element of a list implies traversing it each time. You want to avoid that.
This suggests a representation of lists with extra information for easy access. You only need the last element, but I'll put first and last for symmetry.
-- lists together with their last element
data CL a = CL [a] a a
cl :: [a] -> CL a
cl [] = error "CL from empty list"
cl xs = CL xs (head xs) (last xs)
clSafe :: [a] -> Maybe (CL a)
clSafe [] = Nothing
clSafe xs = Just (cl xs)
clFirst (CL _ x _) = x
clLast (CL _ _ x) = x
compatible cs ds = clLast cs == clFirst ds
Perhaps better, maybe you should have
data CL a = CL [a] a a | Nil
And to include an empty list that is compatible with all others.
Another point to take into account is that if e.g., you have a list xs and want to find lists ys to combine as ys++xs, then you want it to be very easy to access all ys with a given last element. That suggests you should store them in a suitable structure. Maybe a hash table.
In Haskell, how do I implement a function dup that duplicates all elements that are on even positions (0,2,4...) in a list
dup :: [a] -> [a]
dup [] = []
dup (x:xs) = x : x : dup xs
//but only on even index ??
Example of call:
dup [1,5,2,8,4] = [1,1,5,2,2,8,4,4]
Well we can define two functions that perform mutual recursion: dupeven :: [a] -> [a] and dupodd :: [a] -> [a]. dupeven thus will duplicate the first element, and the pass recursively to dupodd. dupodd on the other hand only makes one copy of the head, and then perform recursion on dupeven. Like:
dupeven :: [a] -> [a]
dupeven [] = []
dupeven (x:xs) = x : x : dupodd xs
dupodd :: [a] -> [a]
dupodd [] = []
dupodd (x:xs) = x : dupeven xs
The nice thing is that we get two dupplicate variants. Furthermore both functions are rather simple: they only operate on two different patterns the empty list [] and the "cons" (:).
This thus works as expected, and furthermore we basically have an extra function at (rather) low implementation cost:
Prelude> dupeven [1,5,2,8,4]
[1,1,5,2,2,8,4,4]
Prelude> dupodd [1,5,2,8,4]
[1,5,5,2,8,8,4]
As other answers explain, you can write this function recursively from first principles, but I always think problems like these are interesting puzzles: how can you compose such a function from the existing base library?
First, whenever you want to index a list, you can zip it with a lazily evaluated infinite list:
Prelude> zip [0..] [1,5,2,8,4]
[(0,1),(1,5),(2,2),(3,8),(4,4)]
In this case, though, you don't really need to know the actual index values (0, 1, 2, 3, 4 and so on). Instead, you just need to know how many repetitions of each number you need. You can produce that knowledge by infinitely cycling through 2 and 1:
Prelude> take 10 $ cycle [2,1]
[2,1,2,1,2,1,2,1,2,1]
(The above example uses take 10 to stop evaluation of the list, which, otherwise, continues forever.)
You can zip (cycle [2,1]) with any input list to get a list of tuples:
Prelude> zip (cycle [2,1]) [1,5,2,8,4]
[(2,1),(1,5),(2,2),(1,8),(2,4)]
The first element of the tuple is how many times to repeat the second element.
You can use replicate to repeat any value a number of times, but you'll have to uncurry it to take a single tuple as input:
Prelude> uncurry replicate (2,1)
[1,1]
Prelude> uncurry replicate (1,5)
[5]
Notice that this function always returns a list, so if you do this over a list of tuples, you'll have a list of lists. To immediately flatten such a list, you can therefore use monadic bind to flatten the projection:
Prelude> zip (cycle [2,1]) [1,5,2,8,4] >>= uncurry replicate
[1,1,5,2,2,8,4,4]
You can, if you will, make a function out of it:
dup xs = zip (cycle [2,1]) xs >>= uncurry replicate
This function turns out to be parametrically polymorphic, so while you can use it with lists of integers, you can also use it with lists of characters:
Prelude> dup [1,5,2,8,4]
[1,1,5,2,2,8,4,4]
Prelude> dup "acen"
"aaceen"
You may want to make a mutually recursive set of functions
duplicate, duplicate' :: [a] -> [a]
duplicate [] = []
duplicate (x:xs) = x : x : duplicate' xs
duplicate' [] = []
duplicate' (x:xs) = x : duplicate xs
Or add a simple ADT to determine the next action
data N = O | T
duplicate = duplicate' T
duplicate' _ [] = []
duplicate' T (x:xs) = x : x : duplicate' O xs
duplicate' O (x:xs) = x : duplicate' T xs
But in all honesty, the best way of doing it is what #Simon_Shine suggested,
duplicate [] = []
duplicate (x:y:xs) = x : x : y : duplicate xs
duplicate (x:xs) = x : x : xs -- Here x is an even index and xs is an empty list
I'm trying to solve the following problem found in "Introduction to functional programming" First edition Bird-Wadler.
5 .6.2 The function choose k xs returns a list of all subsequences of xs whose
length is exactly k. For example:
? choose 3 "list"
["ist" , "lst" , "lit" , "lis"]
Give a recursive definition of choose. Show that if xs has length n then
choose k xs has length nk
I only could come up with a non-recursive solution based on a function that returns the list of subsets of an array:
subs :: [a] -> [[a]]
subs [] = [[]]
subs (x:xs) = subs xs ++ map (x:) (subs xs)
choose :: Int -> [a] -> [[a]]
choose x = filter ((== x) . length) . subs
I think you are asking:
What is a lone, recursive function solution to this problem?
These problems usually can be solved if you mentally walk through the base and recursive cases carefully. For example:
Choose is a function from ints and list of values to a list of lists of values:
choose :: Int -> [a] -> [[a]]
If the result is supposed to be 0 length then there is exactly one sublist of said length:
choose 0 _ = [ [] ]
If the result is non-zero but we have no more characters with which to make a sublist then there are no solutions:
choose _ [] = []
Otherwise we can take the first character and append that to all solutions of length one shorter:
choose n (x : xs) =
map (x :) (choose (n - 1) xs)
Or we discard this character (ex, drop 'l' and get the result "ist") and look for a solution with the substring:
++ choose n xs
I am a Haskell beginner and I have been experimenting with recursive functions.
I am working on a function:
separate :: [a] -> [[[a]]]
that takes in a list and outputs all of the partitions of that list.
For example 123 becomes:
1|2|3
12|3
1|23
13|2
132
I have only been able to implement a recursive function that creates the 1|2|3 variant:
separate' :: [a] -> [[a]]
separate' (r:rs) = [r]:separate' xs
>separate [1,2,3]
[[1],[2],[3]]
I am stuck with trying to create the other variants with recursion.
You can think of this function as choosing, for each place in between two list elements, whether to include a split there. So for starters, there should be 2n-1 partitions for an n-element list: you can use that as a quick sanity check on a possible solution.
One good way to model non-determinism is with the list monad (or equivalently with list comprehensions), so let's do it that way.
First, let's write the type and a base case:
separate :: [a] -> [[[a]]]
separate [] = [[]]
There is a single way to separate an empty list: the empty list itself, with no possibility of splits. Easy enough.
Now, given we have one element and a list of remaining elements, one thing we'll need for sure is a list of all the ways to split the remaining elements:
separate :: [a] -> [[[a]]]
separate [] = [[]]
separate (x:xs) = let recur = separate xs
in undefined -- TODO
Here's where the interesting stuff starts. As I said, you can view this as choosing, for each item, whether to put a split after it. Two choices means concatenating together two lists, so let's do that:
separate :: [a] -> [[[a]]]
separate [] = [[]]
separate (x:xs) = let recur = separate xs
split = undefined -- TODO
noSplit = undefined -- TODO
in split ++ noSplit
Now, how do we introduce a split after the item x? We do it by, for each partition in recur, adding [x] to the front of it as a new partition:
separate :: [a] -> [[[a]]]
separate [] = [[]]
separate (x:xs) = let recur = separate xs
split = do
partition <- recur
return $ [x] : partition
noSplit = undefined -- TODO
in split ++ noSplit
What about not splitting? Pretty similar! For each partition in recur, we add x to the front of the first sub-partition:
separate :: [a] -> [[[a]]]
separate [] = [[]]
separate (x:xs) = let recur = separate xs
split = do
partition <- recur
return $ [x] : partition
noSplit = do
(y:ys) <- recur
return $ (x:y):ys
in split ++ noSplit
And with that, we're done:
*Temp> separate "123"
[["1","2","3"],["1","23"],["12","3"],["123"]]
A right fold solution would be:
import Control.Applicative ((<$>))
separate :: Foldable t => t a -> [[[a]]]
separate = foldr (\i -> concatMap (inc i)) [[]]
where
inc i [] = [[[i]]]
inc i (x:xs) = ((i:x):xs):((x:) <$> inc i xs)
then:
\> separate [1, 2]
[[[1,2]],[[2],[1]]]
\> separate [1, 2, 3]
[[[1,2,3]],[[2,3],[1]],[[1,3],[2]],[[3],[1,2]],[[3],[2],[1]]]
I want do do something like:
>enumerate ["banana", "potato", "ice"]
[(1, "banana"), (2, "potato"), (3, "ice")]
I wrote:
enumerate :: [String] -> [(Int, String)]
enumerate [] = []
How may I control/manage the int counter ? Is there a way to do that without a support function ?
Update: I know about Zip function. But for matter of study, I want to implement my own zip function.
Update 2: Currently Code
This is what I did so far, using a support function. Considering that:
1) I want to implement my own zip function;
2) I do not want to change the function struct:
enumerate :: [String] -> [(Int, String)]
enumerate :: [String]->[(Int,String)]
enumerate [] = []
enumerate list = aux 1 list
aux :: Int->[String]->[(Int, String)]
aux _ [] = []
aux i (x:xs) = [(i, x)] ++ aux (i+1) xs
Is it possible to improve this function ? As I don't want to add one more last to the function, so I think support function is the only way to go, right ?
Don't be afraid to write a support function, in fact, see it as opportunity: Why the arbitrary starting value 1? Why not have a function
>enumerateFrom 42 ["banana", "potato", "ice"]
[(42, "banana"), (43, "potato"), (44, "ice")]
Once you have that, enumerate is easy.
Edit:
Either give your aux function a real name, IMHO enumerateFrom is good or move it into a where clause if you know that already. And listen to chi, use x : ... instead of [x] ++ ...
There is already a function which does this called zip (zip :: [a] -> [b] -> [(a,b)]). Now for your function you just can pass a list with 1,2,... as first argument and get your result, e.g.
enumerate :: [String] -> [(Int, String)]
enumerate = zip [1..]
EDIT:
If you also want to implement your own zip function, just use:
zip' :: [a] -> [b] -> [(a,b)]
zip' _ [] = []
zip' [] _ = []
zip' (x:xs) (y:ys) = (x,y):zip' xs ys
You take two lists ([a] and [b]) and put each element into a tuple. Edge cases are of cores when one of the lists is empty you return an empty list. Otherwise you use pattern matching to get the first element of the list put them into a tuple and call zip' again with the tail of the list.
As you clarified you wanted to implement your own zip:
zip' [] _ = []
zip' _ [] = []
zip' (x:xs) (y:ys) = (x,y) : zip' xs ys