I want to print sublists of list having odd length. i coded this.
sublists :: [a] -> [[a]]
sublists [] = [[]]
sublists (x:xs) = if odd (length (tail xs))
then [x:sublist | sublist <- sublists xs] ++ sublists xs
else sublists xs
eg: sublists [1,2,3,4,5,6]
I am getting output as :
[[1,3,5],[1,3],[1,5],[1],[3,5],[3],[5],[]]
I want :
[[1,3,5],[2,3,4],[2,3,5],[1],[2,3,6],[3],[5],[2],[4],[6],[1,2,3],[1,2,4],[1,2,5],[1,2,6],[1,3,4],[1,3,6],[1,4,5],[1,4,6],[1,5,6],[2,4,5],[2,4,6],[2,5,6],[3,4,5],[3,4,6],[3,5,6],[4,5,6],[]]
I think I'd reuse subsequences until I was pretty sure this was the bottleneck. Especially since you seem comfortable calling length a lot, it seems like efficiency isn't a big concern. So:
Data.List> filter (odd . length) . subsequences $ [1..4]
[[1],[2],[3],[1,2,3],[4],[1,2,4],[1,3,4],[2,3,4]]
Related
I'm looking for a function f that, given a list of n elements, computes a list of n sublists of length n-1. Furthermore the nth sublist should contain all but the nth element of the original list. E.g:
f [1..4] == [[2,3,4], [1,3,4], [1,2,4], [1,2,3]]
I found a solution that seems to work, but it looks rather unintuitive:
f :: [a] -> [[a]]
f [] = []
f xs = reverse $ go (length xs - 1) xs
where
go 0 _ = [[]]
go n xs = [ y:ys | y:xs' <- tails xs, ys <- go (n-1) xs' ]
Any suggestions for a more comprehensible solution with reasonable performance?
f xs = [ ys ++ zs | (ys, _ : zs) <- zip (inits xs) (tails xs) ]
inits and tails give you all prefixes and suffixes, in order (take a look at the result of zip (inits xs) (tails xs)). The list comprehension takes one element out of each non-empty suffix (_ : zs), and then concatenates the remaining elements together.
You can simplify a lot by observing that the homework problem contains a recursive structure that neatly matches recursion along the list itself. If you pattern match on the input and it's non-empty, it has a first element of the list then the rest of the list. The rest of the list neatly corresponds to the original list without the first element, so it should be the first output. Then comes the recursion - getting the rest of the results is just a straight-forward application of f to the rest of the list and then fixing up the values so they're the right length and start with the right element.
It's well known that the powerset of a list:
{1,2,3,4} is {{},{1},{2},{1,2},{3},{1,3},{2,3},{1,2,3},{4},{1,4},{2,4},{1,2,4},{3,4},{1,3,4},{2,3,4},{1,2,3,4}}
the haskell code I got for that problem is:
potencia [] = [[]]
potencia (a:bs) = potencia bs ++ map (a:) (potencia bs)
Now, how would I get a list of sublists of the same length?, for example, the list above would generate the next list of sublists of length 3 = {{1,2,3},{1,2,4},{1,3,4}}
I'm a student sorry for my english, thanks in advance... XD
How about
sublists _ 0 = [[]]
sublists [] _ = []
sublists (x:xs) n = sublists xs n ++ map (x:) (sublists xs $ n - 1)
Which is very similar to the code you had but just has two decreasing parameters, the length and the list.
Also, for more advanced Haskellers
powerset = flip runCont id . foldM step [[]]
where step xs x = cont $ \c -> c xs ++ c (map (x:) xs)
is a powerset implementation without recursion using continuations. Doing the same with the sublists function is an interesting challenge.
I'm thinking just
subsequencesOf :: Int -> [a] -> [[a]]
subsequencesOf n = filter ((== n) . length) . subsequences
Which will give you
> subsequencesOf 3 [1, 2, 3, 4]
[[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
Although I find it weird that this isn't an operation in Data.Set, and that Set isn't a monad (and therefore has its own version of replicateM.) I guess there might be obstacles in the way there.
I am trying to write a Haskell code which takes in a list and return a list of list. When I do that as the following code, I am getting "non-exhaustive patterns in function reGroup"
reGroup :: [[Int]] -> [Int] -> [[Int]]
reGroup [[]] [] = [[]]
reGroup [[]] xs = reGroup [(take 3 xs)] (drop 3 xs)
reGroup [[a]] [] = [[a]]
reGroup [[a]] xs = reGroup [[a], (take 3 xs)] (drop 3 xs)
-- calling the reGroup function from another function as follow
reGroup [[]] [1,2,3,4,5,6,7,8,9]
What i want is [1,2,3,4,5,6,7,8,9] -> [[1,2,3], [4,5,6], [7,8,9]]. What am I doing wrong or can someone show me an easy way to it?
It is probably easier to try to do this without the accumulator (the first argument). Then we would have
groupThree :: [a] -> [[a]] --why only work with Ints?
--if the list begins with three elements, stick them in a group
--then group the remainder of the list
groupThree (a:b:c:more) = [a,b,c]:groupThree more
--grouping an empty list gives you an empty list
groupThree [] = []
--if we have some number of elements less than three
--we can just stick them in a list
groupThree other = [other]
Or using drop and take
groupThree :: [a] -> [[a]]
groupThree [] = []
groupThree ls = (take 3 ls):groupThree (drop 3 ls)
which does exactly the same thing.
The reason your code does not work is that
reGroup [xs,ls] y
does not match with any of your cases--you only have code to handle the first argument being a list of exactly one element, that element being the empty list or a list with exactly one element.
The correct use of an accumulator would be
reGroup back [] = back
reGroup back ls = reGroup (back ++ [take 3 ls]) (drop 3 ls)
unfortunately, this is very inefficient since you are appending to the end of a list (taking time proportional to the length of that list...modulo lazieness). Instead, you should use
reGroup back [] = reverse back
reGroup back ls = reGroup ((take 3 ls):back) (drop 3 ls)
although I like the version without an accumulator better since it is lazier (and so can handle infinite lists).
[[a]]
is only a list with a list with one element, like [[1]].
So after one recursion you get from
reGroup [[]] [1,2,3,4,5,6,7,8,9]
to
reGroup [[1,2,3]] [4,5,6,7,8,9]
but for this case (a list with a list with 3 elements) is no pattern defined.
Try this:
reGroup xs n =
if drop n xs == []
then [take n xs]
else [take n xs] ++ (reGroup (drop n xs) n)
Probably not the most efficient, but it's a start.
It outputs:
> reGroup [1..9]
[[1,2,3],[4,5,6],[7,8,9]]
> reGroup [1..10]
[[1,2,3],[4,5,6],[7,8,9],[10]]
And the reason you're getting that error is because you haven't covered all the patterns the function can match. Try throwing in a _ or two for your base case(s).
Changing your code a little to this
reGroup :: [[Int]] -> [Int] -> [[Int]];
reGroup [[]] [] = [];
reGroup a [] = a;
reGroup [[]] xs = reGroup [(take 3 xs)] (drop 3 xs);
reGroup a xs = a ++ reGroup [(take 3 xs)] (drop 3 xs);
does the job.
take3 :: [a] -> [[a]]
take3 [] = []
take3 (x:[]) = [[x]]
take3 (x:y:[]) = [[x,y]]
take3 (x:y:z:xs) = [[x,y,z]] ++ take3 xs
How to define a rotates function that generates all rotations of the given list?
For example: rotates [1,2,3,4] =[[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3]]
I wrote a shift function that can rearrange the order
shift ::[Int]->[Int]
shift x=tail ++ take 1 x
but I don't how to generate these new arrays and append them together.
Another way to calculate all rotations of a list is to use the predefined functions tails and inits. The function tails yields a list of all final segments of a list while inits yields a list of all initial segments. For example,
tails [1,2,3] = [[1,2,3], [2,3], [3], []]
inits [1,2,3] = [[], [1], [1,2], [1,2,3]]
That is, if we concatenate these lists pointwise as indicated by the indentation we get all rotations. We only get the original list twice, namely, once by appending the empty initial segment at the end of original list and once by appending the empty final segment to the front of the original list. Therefore, we use the function init to drop the last element of the result of applying zipWith to the tails and inits of a list. The function zipWith applies its first argument pointwise to the provided lists.
allRotations :: [a] -> [[a]]
allRotations l = init (zipWith (++) (tails l) (inits l))
This solution has an advantage over the other solutions as it does not use length. The function length is quite strict in the sense that it does not yield a result before it has evaluated the list structure of its argument completely. For example, if we evaluate the application
allRotations [1..]
that is, we calculate all rotations of the infinite list of natural numbers, ghci happily starts printing the infinite list as first result. In contrast, an implementation that is based on length like suggested here does not terminate as it calculates the length of the infinite list.
shift (x:xs) = xs ++ [x]
rotates xs = take (length xs) $ iterate shift xs
iterate f x returns the stream ("infinite list") [x, f x, f (f x), ...]. There are n rotations of an n-element list, so we take the first n of them.
The following
shift :: [a] -> Int -> [a]
shift l n = drop n l ++ take n l
allRotations :: [a] -> [[a]]
allRotations l = [ shift l i | i <- [0 .. (length l) -1]]
yields
> ghci
Prelude> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> allRotations [1,2,3,4]
[[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3]]
which is as you expect.
I think this is fairly readable, although not particularly efficient (no memoisation of previous shifts occurs).
If you care about efficiency, then
shift :: [a] -> [a]
shift [] = []
shift (x:xs) = xs ++ [x]
allRotations :: [a] -> [[a]]
allRotations l = take (length l) (iterate shift l)
will allow you to reuse the results of previous shifts, and avoid recomputing them.
Note that iterate returns an infinite list, and due to lazy evaluation, we only ever evaluate it up to length l into the list.
Note that in the first part, I've extended your shift function to ask how much to shift, and I've then a list comprehension for allRotations.
The answers given so far work fine for finite lists, but will eventually error out when given an infinite list. (They all call length on the list.)
shift :: [a] -> [a]
shift xs = drop 1 xs ++ take 1 xs
rotations :: [a] -> [[a]]
rotations xs = zipWith const (iterate shift xs) xs
My solution uses zipWith const instead. zipWith const foos bars might appear at first glance to be identical to foos (recall that const x y = x). But the list returned from zipWith terminates when either of the input lists terminates.
So when xs is finite, the returned list is the same length as xs, as we want; and when xs is infinite, the returned list will not be truncated, so will be infinite, again as we want.
(In your particular application it may not make sense to try to rotate an infinite list. On the other hand, it might. I submit this answer for completeness only.)
I would prefer the following solutions, using the built-in functions cycle and tails:
rotations xs = take len $ map (take len) $ tails $ cycle xs where
len = length xs
For your example [1,2,3,4] the function cycle produces an infinite list [1,2,3,4,1,2,3,4,1,2...]. The function tails generates all possible tails from a given list, here [[1,2,3,4,1,2...],[2,3,4,1,2,3...],[3,4,1,2,3,4...],...]. Now all we need to do is cutting down the "tails"-lists to length 4, and cutting the overall list to length 4, which is done using take. The alias len was introduced to avoid to recalculate length xs several times.
I think it will be something like this (I don't have ghc right now, so I couldn't try it)
shift (x:xs) = xs ++ [x]
rotateHelper xs 0 = []
rotateHelper xs n = xs : (rotateHelper (shift xs) (n - 1))
rotate xs = rotateHelper xs (length xs)
myRotate lst = lst : myRotateiter lst lst
where myRotateiter (x:xs) orig
|temp == orig = []
|otherwise = temp : myRotateiter temp orig
where temp = xs ++ [x]
I suggest:
rotate l = l : rotate (drop 1 l ++ take 1 l)
distinctRotations l = take (length l) (rotate l)
Objective: Finding the permutation of a list such as ["abc", "bc", "acc"]
Problem: My permutation contains doubled and tripled elements and I want to get rid of those elements.
The result that I obtained from the list above is :
[["abc","bc","acc"],["abc","bc"],["abc","acc","bc"],["abc","acc"],["abc","acc"],["abc"],["bc","abc","acc"],["bc","abc"],["bc","acc","abc"],["bc","acc"],["bc","acc"],["bc"],["acc","abc","bc"],["acc","abc"],["acc","bc","abc"],["acc","bc"],["acc","bc"],["acc"],["bc","acc"],["bc"],["acc","bc"],["acc"],["acc"],[]]
The code that I wrote in order to get rid of those doubled elements is stated below:
fct [] = []
fct (xs)
| (head xs) `elem` xs = fct (delete (head xs) xs)
| otherwise = fct xs
Here I wanted to take the first element of the list and compare it with the rest of the list.
Can you help me to find a solution to my problem.
Those are not permutations, because some of them don't contain all the original elements. It seems to be a combination of permutations and selections.
In ghci:
Prelude Data.List Control.Monad> concatMap permutations $ filterM (const [False, True])["abc", "bc", "acc"]
[[],["acc"],["bc"],["bc","acc"],["acc","bc"],["abc"],["abc","acc"],["acc","abc"], ["abc","bc"],["bc","abc"],["abc","bc","acc"],["bc","abc","acc"],["acc","bc","abc"],["bc","acc","abc"],["acc","abc","bc"],["abc","acc","bc"]]
You can use the function nub to remove duplicates from a list.