I have a list like this:
[(2,3),(2,5),(2,7),(3,2),(3,4),(3,6),(4,3),(4,5),(4,7),(5,2),(5,4),(5,6),(6,3),(6,5),(6,7),(7,2),(7,4),(7,6)]
The digits are from [2..7]. I want to take a set where there are any symmetrical pairs. e.g. [(1,2),(2,1)], but those two numbers aren't used again in the set. An example would be:
[(3,6),(6,3),(2,5),(5,2),(4,7),(7,4)]
I wanted to first put symmetric pairs together as I thought it might be easier to work with so i created this function, which actually creates the pairs and puts them in another list
g xs = [ (y,x):(x,y):[] | (x,y) <- xs ]
with which the list turns to this:
[[(3,2),(2,3)],[(5,2),(2,5)],[(7,2),(2,7)],[(2,3),(3,2)],[(4,3),(3,4)],[(6,3),(3,6)],[(3,4),(4,3)],[(5,4),(4,5)],[(7,4),(4,7)],[(2,5),(5,2)],[(4,5),(5,4)],[(6,5),(5,6)],[(3,6),(6,3)],[(5,6),(6,5)],[(7,6),(6,7)],[(2,7),(7,2)],[(4,7),(7,4)],[(6,7),(7,6)]]
Then from here I was hoping to somehow remove duplicates.
I made a function that will look at all of the fst elements of all of the pairs:
flatList xss = [ x | xs <- xss, (x,y) <- xs ]
to use with another function to remove the duplicates.
h (x:xs) | (fst (head x)) `elem` (flatList xs) = h xs
| otherwise = (head x):(last x):(h xs)
which gives me the list
[(3,6),(6,3),(5,6),(6,5),(2,7),(7,2),(4,7),(7,4),(6,7),(7,6)]
which has duplicate numbers. That function only takes into account the first element of the first pair in the list of lists,the problem is when I also take into account the first element of the second pair (or the second element of the first pair):
h (x:xs) | (fst (head x)) `elem` (flatList xs) || (fst (last x)) `elem` (flatList xs) = h xs
| otherwise = (head x):(last x):(h xs)
I only get these two pairs:
[(6,7),(7,6)]
I see that the problem is that this method of deleting duplicates grabs the last repeated element, and would work with a list of digits, but not a list of pairs, as it misses pairs it needs to take.
Is there another way to solve this, or an alteration I could make?
It probably makes more sense to use a 2-tuple of 2-tuples in your list comprehension, since that makes it more easy to do pattern matching, and thus "by contract" enforces the fact that there are two items. We thus can construct 2-tuples that contain the 2-tuples with:
g :: Eq a => [(a, a)] -> [((a, a), (a, a))]
g xs = [ (t, s) | (t#(x,y):ts) <- tails xs, let s = (y, x), elem s ts ]
Here the elem s ts checks if the "swapped" 2-tuple occurs in the rest of the list.
Then we still need to filter the elements. We can make use of a function that uses an accumulator for the thus far obtained items:
h :: Eq a => [((a, a), (a, a))] -> [(a, a)]
h = go []
where go _ [] = []
go seen ((t#(x, y), s):xs)
| notElem x seen && notElem y seen = t : s : go (x:y:seen) xs
| otherwise = go seen xs
For the given sample input, we thus get:
Prelude Data.List> (h . g) [(2,3),(2,5),(2,7),(3,2),(3,4),(3,6),(4,3),(4,5),(4,7),(5,2),(5,4),(5,6),(6,3),(6,5),(6,7),(7,2),(7,4),(7,6)]
[(2,3),(3,2),(4,5),(5,4),(6,7),(7,6)]
after reading a few times your question, I got an elegant solution to your problem. Thinking that if you have a list of pairs without any repeated number, you can get the list of swapped pairs easily, solving your problem. So your problem can be reduce to given a list, get the list of all pairs using each number just one.
For a given list, there are many solutions to this, ex: for [1,2,3,4] valid solutions are: [(2,4),(4,2),(1,3),(3,1)] and [(2,3),(3,2),(1,4),(4,1)], etc... The approach here is:
take a permutation if the original list (say [1,4,3,2])
pick one element for each half and pair them together (for simplicity, you can pick consecutive elements too)
for each pair, create a the swapped pair and put all together
By doing so you end up with a list of non repeating numbers of pairs and its symmetric. More over, looping around all permutaitons, you can get all the solutions to your problem.
import Data.List (permutations, splitAt)
import Data.Tuple (swap)
-- This function splits a list by the half of the length
splitHalf :: [a] -> ([a], [a])
splitHalf xs = splitAt (length xs `quot` 2) xs
-- This zip a pair of list into a list of pairs
zipHalfs :: ([a], [a]) -> [(a,a)]
zipHalfs (xs, ys) = zip xs ys
-- Given a list of tuples, creates a larger list with all tuples and all swapped tuples
makeSymetrics :: [(a,a)] -> [(a,a)]
makeSymetrics xs = foldr (\t l -> t:(swap t):l) [] xs
-- This chain all of the above.
-- Take all permutations of xs >>> for each permutations >>> split it in two >>> zip the result >>> make swapped pairs
getPairs :: [a] -> [[(a,a)]]
getPairs xs = map (makeSymetrics . zipHalfs . splitHalf) $ permutations xs
>>> getPairs [1,2,3,4]
[[(1,3),(3,1),(2,4),(4,2)],[(2,3),(3,2),(1,4),(4,1)] ....
Related
I'm new to Haskell and need to list all possible ways to pair up (even) lists of Ints.
E.g.
[1,2,3,4] -> [[(1,2),(3,4)], [(2,3),(1,4)], [(1,3),(2,4)], ...]
Generating all possible pairs is easy enough (shown below) but I can't work out how to return only ways to pair up the entire input list.
pairs :: [a] -> [[(a, a)]]
pairs l = [(x,y) | (x:ys) <- tails l, y <- ys]
I recommend writing a function that nondeterministically chooses an element, returning the rest of the values in the list as well. There are a few possible APIs; the one I suggest below is the most general-purpose one, and one I've used on many occasions for apparently unrelated tasks.
zippers :: [a] -> [([a], a, [a])]
Here's an example of what this function does:
> zippers "abcd"
[("", 'a', "bcd"), ("a", 'b', "cd"), ("ba", 'c', "d"), ("cba", 'd', "")]
Once you have that, you can simply repeatedly non-deterministically choose an element from the ever-shrinking list of available options, making a pair after every other choice.
We can make use of a helper function pick that returns a list of 2-tuples with as first element the item picked, and a second element a list of remaining elements:
pick :: [a] -> [(a, [a])]
pick [] = []
pick (x:xs) = (x, xs) : …
where the … part should make a call to pick with the tail of the list, and prepend each second item of the 2-tuples returned with x.
With this pick function we can then construct all combinations with:
pairs :: [a] -> [[(a, a)]]
pairs [] = [[]]
pairs (x:xs) = [(x,y):tl | (y, zs) <- pick xs, tl <- pairs zs]
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.
I'm really new to programming and Haskell in particular (so new that I actually don't know if this is a stupid question or not). But I was watching the lecture given by Eric Meijer (http://channel9.msdn.com/Series/C9-Lectures-Erik-Meijer-Functional-Programming-Fundamentals) and i was fascinated by the program written by Dr. Graham Hutton in lecture 11; The countdown problem.
My question is:
Is there a way of "filtering" the list of solutions by the length (number of elements), so that the list of solutions are restricted to the solutions that only uses (for example) three of the source numbers? In other words, I would like to change the question from "given the numbers [1,2,3,4,5,6,8,9] construct 18 using the operators..." to "given the numbers [..] which three numbers can be used to construct..."
In my futile attempts, I've been trying to put a kind restriction on his function subbags (which returns all permutations and subsequences of a list)
subbags :: [a] -> [[a]]
subbags xs = [zs | ys <- subs xs, zs <- perms ys]
So that I get all the permutations and subsequences that only contain three of the source numbers. Is this possible? If so, how?
Like I said, I have no idea if this is even a legitimate question - but I have gone from curious to obsessed, so any form of help or hint would be greatly appreciated!
The simplest way would be to just select from the candidates three times
[ (x, y, z) | x <- xs, y <- xs, z <- xs ]
although this assumes that repeat use of a single number is OK.
If it's not, we'll have to get smarter. In a simpler scenario we'd like to pick just two candidates:
[ (x, y) | x <- xs, y <- ys, aboveDiagonal (x, y) ]
in other words, if we think of this as a cartesian product turning a list into a grid of possibilities, we'd like to only consider the values "above the diagonal", where repeats don't happen. We can express this by zipping the coordinates along with the values
[ (x, y) | (i, x) <- zip [1..] xs
, (j, y) <- zip [1..] xs
, i < j
]
which can be extended back out to the n=3 scenario
[ (x, y, z) | (i, x) <- zip [1..] xs
, (j, y) <- zip [1..] xs
, (k, z) <- zip [1..] xs
, i < j
, j < k
]
Ultimately, however, this method is inefficient since it still has to scan through all of the possible pairs and then prune the repeats. We can be a bit smarter by only enumerating the above diagonal values to begin with. Returning to n=2 we'll write this as
choose2 :: [a] -> [(a, a)]
choose2 [] = []
choose2 (a:as) = map (a,) as ++ choose2 as
In other words, we pick first all of the pairs where the head of the list comes first and a value in the tail of the list comes second—this captures one edge of the upper triangle—and then we recurse by adding all of the upper diagonal values of the list of candidates sans the head.
This method can be straightforwardly extended to the n=3 case by using the n=2 case as a building block
choose3 :: [a] -> [(a, a, a)]
choose3 [] = []
choose3 (a:as) = map (\(y, z) -> (a, y, z)) (choose2 as) ++ choose3 as
which also provides a direct generalization to the fully general n dimensional solution
choose :: Int -> [a] -> [[a]]
choose 0 as = [[]] -- there's one way to choose 0 elements
choose _ [] = [] -- there are 0 ways to choose (n>0) elements of none
choose 1 as = map (:[]) as -- there are n ways to choose 1 element of n
choose n (a:as) = map (a:) (choose (n-1) as) ++ choose n as
I like this solution, which does not require the list elements to be an instance of Eq:
import Data.List (tails)
triples ls = [[x,y,z] | (x:xs) <- tails ls,
(y:ys) <- tails xs,
z <- ys]
This returns only subsequences, not permutations, though.
How do I manually split [1,2,4,5,6,7] into [[1],[2],[3],[4],[5],[6],[7]]? Manually means without using break.
Then, how do I split a list into sublists according to a predicate? Like so
f even [[1],[2],[3],[4],[5],[6],[7]] == [[1],[2,3],[4,5],[6,7]]
PS: this is not homework, and I've tried for hours to figure it out on my own.
To answer your first question, this is rather an element-wise transformation than a split. The appropriate function to do this is
map :: (a -> b) -> [a] -> [b]
Now, you need a function (a -> b) where b is [a], as you want to transform an element into a singleton list containing the same type. Here it is:
mkList :: a -> [a]
mkList a = [a]
so
map mkList [1,2,3,4,5,6,7] == [[1],[2],...]
As for your second question: If you are not allowed (homework?) to use break, are you then allowed to use takeWhile and dropWhile which form both halves of the result of break.
Anyway, for a solution without them ("manually"), just use simple recursion with an accumulator:
f p [] = []
f p (x:xs) = go [x] xs
where go acc [] = [acc]
go acc (y:ys) | p y = acc : go [y] ys
| otherwise = go (acc++[y]) ys
This will traverse your entire list tail recursively, always remembering what the current sublist is, and when you reach an element where p applies, outputting the current sublist and starting a new one.
Note that go first receives [x] instead of [] to provide for the case where the first element already satisfies p x and we don't want an empty first sublist to be output.
Also, this operates on the original list ([1..7]) instead of [[1],[2]...]. But you can use it on the transformed one as well:
> map concat $ f (odd . head) [[1],[2],[3],[4],[5],[6],[7]]
[[1,2],[3,4],[5,6],[7]]
For the first, you can use a list comprehension:
>>> [[x] | x <- [1,2,3,4,5,6]]
[[1], [2], [3], [4], [5], [6]]
For the second problem, you can use the Data.List.Split module provided by the split package:
import Data.List.Split
f :: (a -> Bool) -> [[a]] -> [[a]]
f predicate = split (keepDelimsL $ whenElt predicate) . concat
This first concats the list, because the functions from split work on lists and not list of lists. The resulting single list is the split again using functions from the split package.
First:
map (: [])
Second:
f p xs =
let rs = foldr (\[x] ~(a:r) -> if (p x) then ([]:(x:a):r) else ((x:a):r))
[[]] xs
in case rs of ([]:r) -> r ; _ -> rs
foldr's operation is easy enough to visualize:
foldr g z [a,b,c, ...,x] = g a (g b (g c (.... (g x z) ....)))
So when writing the combining function, it is expecting two arguments, 1st of which is "current element" of a list, and 2nd is "result of processing the rest". Here,
g [x] ~(a:r) | p x = ([]:(x:a):r)
| otherwise = ((x:a):r)
So visualizing it working from the right, it just adds into the most recent sublist, and opens up a new sublist if it must. But since lists are actually accessed from the left, we keep it lazy with the lazy pattern, ~(a:r). Now it works even on infinite lists:
Prelude> take 9 $ f odd $ map (:[]) [1..]
[[1,2],[3,4],[5,6],[7,8],[9,10],[11,12],[13,14],[15,16],[17,18]]
The pattern for the 1st argument reflects the peculiar structure of your expected input lists.
I have two lists. One list contains some random data and other list contains the index of first list which needs to be deleted.
For example, let us consider two lists:
let a = [3,4,5,6,6,7,8]
let b = [1,3]
Then, the resultant output should be [3,5,6,7,8]. The number 4 and 6 are deleted since they are on index positions 1 and 3 respectively.
I'm new to Haskell, so finding it difficult to find the solution.
Update: Following code makes it work
import Data.List
dele :: Eq a => [a] -> [Int] -> [a]
dele [] _ = []
dele x [] = x
dele x (y:ys) = dele (delete (x !! y) x) ys
I was just wondering, is there a way to solve it through map/fold way ?
deleteByIndex :: (Enum a, Eq a, Num a) => [a] -> [b] -> [b]
deleteByIndex r = map snd . filter (\(i, _) -> notElem i r) . zip [0..]
[0..] produces an infinite list [0, 1, 2, 3, ...]
zip constructs a list of pairs with the values of this list and your input list in the form [(0,x), (1, y), ...]
filter takes a function a -> Bool. The lambda checks if the index (first element of the pair) is in your input list r.
map snd returns the second element of each pair of the zip list.
zip,filter, map and notElem are documented here
Off the top of my head:
removeByIndex :: [Integer] -> [a] -> [a]
removeByIndex indices = map snd . filter notInIndices . zip [0..]
where notInIndices (i,_) = i `notElem` indices
An alternative answer using the lens library which has received considerable attention recently
import Control.Lens
>let a = [3,4,5,6,6,7,8]
>let b = [1,3]
>a^..elements (`notElem`b)
[3,5,6,7,8]
(^..) is jus the infix for of toListOf which can be used to traverse a structure and make a list out of its parts. The elements function just lets you choose which ones to include.
Other options are 'traverse' to traverse a traversables, 'both' to traverse a (,) and they compose together with (.) so traverse.both would traverse [(1,2), (3,4)] for example.
[(1,2), (3,4)]^..traverse.both
[1,2,3,4]