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
Related
I want to create a function which takes in a list ["1","2","3","4"] and returns a list of tuples [(1,2),(3,4)], but im not sure how to code it
every n xs = case drop (n-1) xs of
(y:ys) -> y : every n ys
[] -> []
tup :: [String] -> [(Int, Int)]
tup xs = [((read c),(read i)) | c <- (every 1 xs), i <-(every 2 xs)]
is what ive tried but the output is wrong
output:
*Main> tup ["1", "2", "3", "4"]
[(1,2),(1,4),(2,2),(2,4),(3,2),(3,4),(4,2),(4,4)]
You could use pattern matching:
tup [] = []
tup [_] = []
tup (a:b:other) = (read a, read b):(tup other)
The first two cases deal with the empty list and a list of one element. It doesn't make sense to construct a list of tuples out of these, so the function just returns the empty list. The last case simply extracts the two leading values, puts them into a tuple and prepends it to whatever the recursive call returns.
Define a helper function mergers that given all parts of a word, produces a pair of all possible ways to break up the word. This recursively. The concat function might help you.
I can seem to use map and concat to solve this problem. I've solved the first 3 cases which were much easier but cant solve the last one.
mergers :: [String] ->[(String,String)]
mergers [] = []
mergers (x:xs)
| xs ==[] = []
mergers (x:xs:xy)
| xy ==[] = [(x,xs)]
mergers (x:xs:xy:_) ->
The function:
mergers ["co","nt","ro","ls"]
should produce all the possible combination of the given strings like
[("co","ntrols"),("cont","rols"),("contro","ls")]
mergers ["co","nt"]
should give
[("co","nt")]
mergers ["co"]
should return an empty list
[]
The given function will not suffice. Especially since you need to keep track of the items that have passed. We thus probably should use a helper function that keeps track of the items obtained thus far. These items are then put in a concatenated form in the first tuple.
We thus can work with a helper function, like:
mergers :: [[a]] -> [([a], [a])]
mergers [] = []
mergers (x:xs) = helper [x] xs
where helper left right = …
Now in the helper function, if the right list is empty, than we can stop to produce a list. If on the other hand the right list is not-empty, we can emit a 2-tuple where we concatenate both the left and the right in the tuple, and add the first item of the right list to the left if we recurse.
EDIT: since you managed to solve it, we can here yield the items with:
mergers :: [[a]] -> [([a], [a])]
mergers [] = []
mergers (x:xs) = helper [x] xs
where helper _ [] = []
helper la ra#(r:rs) = (concat la, concat ra) : helper (la ++ [r]) rs
This then yields the expected output:
Prelude> mergers ["co","nt","ro","ls"]
[("co","ntrols"),("cont","rols"),("contro","ls")]
Prelude> mergers ["co","nt"]
[("co","nt")]
Prelude> mergers ["co"]
[]
So, I know, there is a built in function to reverse a list in Haskell, but I'm trying to write my own little function, just to practice some Haskell. I thought of the following code, which sadly is not working. Could you guys tell me what I did wrong?
rev :: [Int] -> [Int]
rev [] = []
rev [x] = last [x] : rev init [x]
If you want to do it efficiently, I'd recommend you use an accumulator:
rev :: [a] -> [a]
rev xs = go xs []
where
go :: [a] -> [a] -> [a]
go [] ys = ys
go (x:xs) ys = go xs (x:ys)
The function go, at each step, removes one element from the first list xs and prepends it to the second list ys. This is similar to popping from a stack and pushing to another stack -- which reverses the order.
Since we only use a constant amount of time at each recursive call, we get O(n) complexity, where n is the list length.
Instead, if at each recursive call we use last or append with ... ++ [x], we pay O(n) for each call, hence O(n^2) overall.
You almost had it.
rev :: [Int] -> [Int]
rev [] = []
rev x = last x : rev (init x)
Explanation: [x] was a list containing x, whereas you want to operate directly with x
ps. here's the documentation for Data.List. And remember to import Data.List
Well, you could do something like this:
rev :: [Int] -> [Int]
rev [] = []
rev (x:l) = (rev l) ++ [x]
The 3rd line takes the first element from the list and then creates a list containing only that element. This is appended to the result of the recursion rev l call.
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 have a signature
combine
:: [[a]] -> [[a]]
function Combine takes list built from list,(1 list may be infinity, like repeat 1), and returns list
with the longest list(s) without changing their order.
combine [] = []
combine [[]] = [[]]
combine [[], [1]] = [[1]]
combine [[1], [2]] = [[1],[2]]
combine [[], repeat 1, []] = [repeat 1] value
Any ideas?
Thank you
Code:
combine :: [[a]] -> [[a]]
combine [] = []
combine ((xs),[]) = [xs] doesnt work for some reason
You will need to solve this with a recursive function.
Consider a recursive algorithm that builds an accumulator -- ask for clarification if you are not familiar with the concept of an accumulator. This accumulator will have type [[a]], which is the same as our function's return type. As we iterate over the list of lists using a recursive function, we cons lists onto the accumulator if they are the same length as other lists in the accumulator, or ignore them if they are of less length. However, if the list is of greater length, we scrap everything else in the accumulator and only keep the new, longer list.
This vaguely describes a linear algorithm you may use to solve this problem. Please ask questions in the comments if you wish for more clarification.
First, you need a compare function, e.g.:
cmp [] [] = EQ
cmp [] _ = LT
cmp _ [] = GT
cmp (x:xs) (y:ys) = cmp xs ys
Then you can use a helper function that has an accumulator for the current "maximums":
combine :: [[a]] -> [[a]]
combine [] = []
combine (x:xs) = comb xs [x] where
comb [] acc = acc
comb (x:xs) (y:ys) = case x `cmp` y of
EQ -> ???
LT -> ???
GT -> ???
I think you can figure out what to do in the different cases...