Haskell: Split a list using list comprehension - haskell

How do you split a list into halves using list comprehension?
e.g. If I have [1,1,2,2,3,3,4,4,5,5] and I only want [1,1,2,2,3]
my attempts so far:
half mylist = [r | mylist!r ; r <- [0..(#mylist div 2)] ] ||does not work
Any thoughts?
[Nb: This isn't actually Haskell but similar. ! is used for indexing list, and # gives length)
Edit::
Okay so it turns out that
half mylist = [r | r <- [mylist!0..mylist!(#mylist div 2)] ]
works, but only in list of numbers and not strings. Any clues?

This isn't really an appropriate thing to do with a list comprehension. List comprehensions are alternate syntax for maps and filters (and zips). Splitting a list is a fold.
As such, you should consider a different approach. E.g.
halve :: [a] -> [a]
halve [] = []
halve xs = take (n `div` 2) xs
where n = length xs
Splitting isn't a great operation on large lists, since you take the length first (so it is always n + n/2 operations on the list. It is more appropriate for array-like types that have O(1) length and split.

Another possible solution, using a boolean guard:
half xs = [x | (x,i) <- zip xs [1..], let m = length xs `div` 2, i <= m]
But as Don Stewart says, a list comprehension is not really the right tool for this job.

Related

Haskell 99 Questions #27

I'm having trouble conceptualizing given answer for problem 27 in haskell's 99 problems https://wiki.haskell.org/99_questions/Solutions/27.
The Problem:
"
Group the elements of a set into disjoint subsets.
a) In how many ways can a group of 9 people work in 3 disjoint subgroups of 2, 3 and 4 persons? Write a function that generates all the possibilities and returns them in a list.
Example:
* (group3 '(aldo beat carla david evi flip gary hugo ida))
( ( (ALDO BEAT) (CARLA DAVID EVI) (FLIP GARY HUGO IDA) )
... )
b) Generalize the above predicate in a way that we can specify a list of group sizes and the predicate will return a list of groups.
"
The answer they give is this:
combination :: Int -> [a] -> [([a],[a])]
combination 0 xs = [([],xs)]
combination n [] = []
combination n (x:xs) = ts ++ ds
where
ts = [ (x:ys,zs) | (ys,zs) <- combination (n-1) xs ]
ds = [ (ys,x:zs) | (ys,zs) <- combination n xs ]
group :: [Int] -> [a] -> [[[a]]]
group [] _ = [[]]
group (n:ns) xs =
[ g:gs | (g,rs) <- combination n xs
, gs <- group ns rs ]
I'm having a lot of trouble understanding how the first section (the section defining the function "combination") operates.
I'm pretty new to haskell too, so explain it to me like I'm in 5th grade.
Any feedback appreciated.
combination 0 xs = [([],xs)]
If we want to choose 0 elements from xs, there is only one way. No elements are taken [] and all the elements xs are left there.
combination n [] = []
Otherwise, we want to choose n (>0) elements. If we want to chose them from the empty list [], there are no ways to do that -- it's impossible.
combination n (x:xs) = ts ++ ds
where
ts = [ (x:ys,zs) | (ys,zs) <- combination (n-1) xs ]
ds = [ (ys,x:zs) | (ys,zs) <- combination n xs ]
Otherwise, we want to choose n (>0) elements from a nonempty list x:xs. There are many ways to do that, which we separate in two groups as follows:
we decide to take the element x among the chosen ones, and we are left with choosing n-1 from xs. This is done in ts, which considers all the ways to choose n-1 elements from xs, and then adds x to the list of "chosen" elements ys.
we decide to drop the element x from the input list, and we are left with choosing n from xs. This is done in ds, which considers all the ways to choose n elements from xs, and then adds x to the list of "dropped" elements zs.
We then output all such combinations using ts++ds.
Function combination takes list and one number. It creates the combination of the list considering the list has to be divided only in two parts. This is simply the original problem reduced only with 2 numbers k and n-k.
It does this using ts and ds lists.
ts is when the first element is in first part and then recursion occurs with remaining list and k-1. ds is where first element is in second part and recursion occurs with k and remaining part. Once remaining part is computed first element is added to it.

Haskell - Generating Subsets of Length k

I have a Haskell function that computes subsets of a set.
subsets :: [a] -> [[a]]
subsets [] = [[]]
subsets (x:xs) = [zs | ys <- subsets xs, zs <- [ys, (x:ys)]]
Example of use:
*Main> subsets [1,2,3]
[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
If I add the definition:
ksubsets k xs = [ys | ys<-subsets xs, length ys==k]
I can compute the subsets of a set of n elements where each subset has exactly k elements
Example of use:
*Main> ksubsets 3 [1,2,3,4,5]
[[1,2,3],[1,2,4],[1,3,4],[2,3,4],[1,2,5],[1,3,5],[2,3,5],[1,4,5],[2,4,5],
[3,4,5]]
How could I create a more efficient function that generates the subsets of a set with n elements having exactly k elements but without generating all of the subsets. How do I only find the subsets of k elements.
Let's consider some recursive definitions, without going into code quite yet.
If you want to get every subset of size n, then you might pick an element, and append that to a subset of size n-1. If we do that for each element, then we should get all subsets of size n. That's a useful starting point!
Let's put that into code now:
-- A base case:
subsetsOfSize 0 _ = [[]]
-- If there are no elements, there are no subsets:
subsetsOfSize _ [] = []
-- The case discussed above:
subsetsOfSize n (x:xs) =
[x : subs | subs <- subsetsOfSize (n-1) xs] -- ones starting with x,
++ subsetsOfSize n xs -- ones starting with other elements.
As for efficiency? That's left to you, since this does look a bit like work you should be doing on your own. What do you think is inefficient about this function? Here are a few ideas:
If the length of a list list is m, and m is less than n, then subsetsOfSize n list = []. Do we check for that already?
It's well-known that ++ is not performant. What could we use instead? Is there a way to 'rephrase' this function?

Enumerate All Finite Sequences of Integers?

I want to write a Haskell list comprehension to enumerate all finite sequences of integers.
I'm pretty sure that this set is countable.
This is what I have so far:
enumIntSeqs = [ (x, [ ( x, [0..x] ) | x <- [ x | x <- [0..x] ] ] ) | x <- [0..] ]
Another idea I have is to somehow list every finite path in the infinite array
Z* X Z* where Z* = {0, 1, -1, 2, -2,...}
This is, indeed, possible. But it is not easy. Imagine you have an enumeration of all integers, an enumeration of all pairs of integers, an enumeration of all triples of integers, etc. Then you need to choose "fairly" from those enumerations to be sure to hit each element of each. A similar problem will arise when you try even to enumerate all pairs of integers. I suggest you start with that problem, and then look into something like Control.Monad.Omega, or perhaps even Control.Monad.Logic.
I am not going to spoil your fun by attempting a full answer, so let me just demonstrate a handful of things through the simplified problem of enumerating all finite, non-empty, sequences of contiguous naturals starting from zero -- something that you seem close to achieving on your own already. The key steps are already amidst your enumIntSeqs, but you don't have to nest list comprehensions like that. If you begin with...
[ {- etc. -} | x <- [0..] ]
... you can generate a new list for each x simply by doing...
[ {- etc. -} | x <- [0..], let ys = [0..x] ]
... and then returning those lists:
[ ys | x <- [0..], let ys = [0..x] ]
(Note that I didn't write ys <- [0..x]. Try to predict what would happen in that case, and then check it in GHCi.)
The separate let definition isn't necessary, nor does it add anything in terms of clarity in this simple comprehension, so we can just write:
[ [0..x] | x <- [0..] ]
And that's it.
Prelude> take 4 $ [ [0..x] | x <- [0..] ]
[[0],[0,1],[0,1,2],[0,1,2,3]]
P.S.: Two other ways of writing the enumeration. Using do-notation...
someIntSeqs = do
x <- [0..]
return [0..x]
... and with a humble fmap (which in this case is the same as map):
Prelude> take 4 $ fmap (\x -> [0..x]) [0..]
[[0],[0,1],[0,1,2],[0,1,2,3]]
Prelude> -- Or, equivalently...
Prelude> take 4 $ (\x -> [0..x]) <$> [0..]
[[0],[0,1],[0,1,2],[0,1,2,3]]
I don't know if this is what you want, because your question wasn't very clear, but given the example that you provided [0,1,-1,-2,2..], I'm going to give a few examples of how to produce a sorted list of integers, and change it according to your needs.
numberline :: Integer -> [Integer]
numberline n = line (-abs n) (abs n) []
where
line 0 0 l = (0:l)
line r s t = r : line (r+1) (s-1) (s:t)
What it does is to ensure that there is a positive and negative number, with the use of -abs and abs as inputs, so that the line function returns them in that order. Then, you only need to map this function to a list of an arbitrary size to get a list of lists with integers ranging from a negative number to its symmetric end.
map numberline [1..2] -- [[-1,0,1],[-2,-1,0,1,2]]
map numberline [1..] -- [[-1,0,1],[-2,-1,0,1,2],[-3,-2,-1,0,1,2,3]..
So how do you change the above piece of code to generate an alternating path between integers as pairs of natural numbers in some array without repeating them?
countable :: Integer -> [Integer]
countable n = count (-abs n) (abs n) []
where
count 0 0 l = (0:l)
count r s t = count (r+1) (s-1) (s:r:t)
The end result being [0,1,-1,2,-2,3,-3] for countable 3. It's not very efficient for big numbers, so you may want to consider a list starting from the argument down to 0 instead of the other way around.
I hope that I helped.

Dovetail iteration over infinite lists in Haskell

I want to iterate 2 (or 3) infinite lists and find the "smallest" pair that satisfies a condition, like so:
until pred [(a,b,c) | a<-as, b<-bs, c<-cs]
where pred (a,b,c) = a*a + b*b == c*c
as = [1..]
bs = [1..]
cs = [1..]
The above wouldn't get very far, as a == b == 1 throughout the run of the program.
Is there a nice way to dovetail the problem, e.g. build the infinite sequence [(1,1,1),(1,2,1),(2,1,1),(2,1,2),(2,2,1),(2,2,2),(2,2,3),(2,3,2),..] ?
Bonus: is it possible to generalize to n-tuples?
There's a monad for that, Omega.
Prelude> let as = each [1..]
Prelude> let x = liftA3 (,,) as as as
Prelude> let x' = mfilter (\(a,b,c) -> a*a + b*b == c*c) x
Prelude> take 10 $ runOmega x'
[(3,4,5),(4,3,5),(6,8,10),(8,6,10),(5,12,13),(12,5,13),(9,12,15),(12,9,15),(8,15,17),(15,8,17)]
Using it's applicative features, you can generalize to arbitrary tuples:
quadrupels = (,,,) <$> as <*> as <*> as <*> as -- or call it liftA4
But: this alone does not eliminate duplication, of course. It only gives you proper diagonalization. Maybe you could use monad comprehensions together with an approach like Thomas's, or just another mfilter pass (restricting to b /= c, in this case).
List comprehensions are great (and concise) ways to solve such problems. First, you know you want all combinations of (a,b,c) that might satisfy a^2 + b^2 = c^2 - a helpful observation is that (considering only positive numbers) it will always be the case that a <= c && b <= c.
To generate our list of candidates we can thus say c ranges from 1 to infinity while a and b range from one to c.
[(a,b,c) | c <- [1..], a <- [1..c], b <- [1..c]]
To get to the solution we just need to add your desired equation as a guard:
[(a,b,c) | c <- [1..], a <- [1..c], b <- [1..c], a*a+b*b == c*c]
This is inefficient, but the output is correct:
[(3,4,5),(4,3,5),(6,8,10),(8,6,10),(5,12,13),(12,5,13),(9,12,15)...
There are more principled methods than blind testing that can solve this problem.
{- It depends on what is "smallest". But here is a solution for a concept of "smallest" if tuples were compared first by their max. number and then by their total sum. (You can just copy and paste my whole answer into a file as I write the text in comments.)
We will need nub later. -}
import Data.List (nub)
{- Just for illustration: the easy case with 2-tuples. -}
-- all the two-tuples where 'snd' is 'n'
tuples n = [(i, n) | i <- [1..n]]
-- all the two-tuples where 'snd' is in '1..n'
tuplesUpTo n = concat [tuples i | i <- [1..n]]
{-
To get all results, you will need to insert the flip of each tuple into the stream. But let's do that later and generalize first.
Building tuples of arbitrary length is somewhat difficult, so we will work on lists. I call them 'kList's, if they have a length 'k'.
-}
-- just copied from the tuples case, only we need a base case for k=1 and
-- we can combine all results utilizing the list monad.
kLists 1 n = [[n]]
kLists k n = do
rest <- kLists (k-1) n
add <- [1..head rest]
return (add:rest)
-- same as above. all the klists with length k and max number of n
kListsUpTo k n = concat [kLists k i | i <- [1..n]]
-- we can do that unbounded as well, creating an infinite list.
kListsInf k = concat [kLists k i | i <- [1..]]
{-
The next step is rotating these lists around, because until now the largest number is always in the last place. So we just look at all rotations to get all the results. Using nub here is admittedly awkward, you can improve that. But without it, lists where all elements are the same are repeated k times.
-}
rotate n l = let (init, end) = splitAt n l
in end ++ init
rotations k l = nub [rotate i l | i <- [0..k-1]]
rotatedKListsInf k = concatMap (rotations k) $ kListsInf k
{- What remains is to convert these lists into tuples. This is a bit awkward, because every n-tuple is a separate type. But it's straightforward, of course. -}
kListToTuple2 [x,y] = (x,y)
kListToTuple3 [x,y,z] = (x,y,z)
kListToTuple4 [x,y,z,t] = (x,y,z,t)
kListToTuple5 [x,y,z,t,u] = (x,y,z,t,u)
kListToTuple6 [x,y,z,t,u,v] = (x,y,z,t,u,v)
{- Some tests:
*Main> take 30 . map kListToTuple2 $ rotatedKListsInf 2
[(1,1),(1,2),(2,1),(2,2),(1,3),(3,1),(2,3),(3,2),(3,3),(1,4),(4,1),(2,4),(4,2),(3,4),
(4,3),(4,4),(1,5),(5,1),(2,5),(5,2),(3,5),(5,3),(4,5),(5,4),(5,5),(1,6),(6,1),
(2,6), (6,2), (3,6)]
*Main> take 30 . map kListToTuple3 $ rotatedKListsInf 3
[(1,1,1),(1,1,2),(1,2,1),(2,1,1),(1,2,2),(2,2,1),(2,1,2),(2,2,2),(1,1,3),(1,3,1),
(3,1,1),(1,2,3),(2,3,1),(3,1,2),(2,2,3),(2,3,2),(3,2,2),(1,3,3),(3,3,1),(3,1,3),
(2,3,3),(3,3,2),(3,2,3),(3,3,3),(1,1,4),(1,4,1),(4,1,1),(1,2,4),(2,4,1),(4,1,2)]
Edit:
I realized there is a bug: Just rotating the ordered lists isn't enough of course. The solution must be somewhere along the lines of having
rest <- concat . map (rotations (k-1)) $ kLists (k-1) n
in kLists, but then some issues with repeated outputs arise. You can figure that out, I guess. ;-)
-}
It really depends on what you mean by "smallest", but I assume you want to find a tuple of numbers with respect to its maximal element - so (2,2) is less than (1,3) (while standard Haskell ordering is lexicographic).
There is package data-ordlist, which is aimed precisely at working with ordered lists. It's function mergeAll (and mergeAllBy) allows you to combine a 2-dimensional matrix ordered in each direction into an ordered list.
First let's create a desired comparing function on tuples:
import Data.List (find)
import Data.List.Ordered
compare2 :: (Ord a) => (a, a) -> (a, a) -> Ordering
compare2 x y = compare (max2 x, x) (max2 y, y)
where
max2 :: Ord a => (a, a) -> a
max2 (x, y) = max x y
Then using mergeAll we create a function that takes a comparator, a combining function (which must be monotonic in both arguments) and two sorted lists. It combines all possible elements from the two lists using the function and produces a result sorted list:
mergeWith :: (b -> b -> Ordering) -> (a -> a -> b) -> [a] -> [a] -> [b]
mergeWith cmp f xs ys = mergeAllBy cmp $ map (\x -> map (f x) xs) ys
With this function, it's very simple to produce tuples ordered according to their maximum:
incPairs :: [(Int,Int)]
incPairs = mergeWith compare2 (,) [1..] [1..]
Its first 10 elements are:
> take 10 incPairs
[(1,1),(1,2),(2,1),(2,2),(1,3),(2,3),(3,1),(3,2),(3,3),(1,4)]
and when we (for example) look for the first pair whose sum of squares is equal to 65:
find (\(x,y) -> x^2+y^2 == 65) incPairs
we get the correct result (4,7) (as opposed to (1,8) if lexicographic ordering were used).
This answer is for a more general problem for a unknown predicate. If the predicate is known, more efficient solutions are possible, like others have listed solutions based on knowledge that you don't need to iterate for all Ints for a given c.
When dealing with infinite lists, you need to perform breadth-first search for solution. The list comprehension only affords depth-first search, that is why you never arrive at a solution in your original code.
counters 0 xs = [[]]
counters n xs = concat $ foldr f [] gens where
gens = [[x:t | t <- counters (n-1) xs] | x <- xs]
f ys n = cat ys ([]:n)
cat (y:ys) (x:xs) = (y:x): cat ys xs
cat [] xs = xs
cat xs [] = [xs]
main = print $ take 10 $ filter p $ counters 3 [1..] where
p [a,b,c] = a*a + b*b == c*c
counters generates all possible counters for values from the specified range of digits, including a infinite range.
First, we obtain a list of generators of valid combinations of counters - for each permitted digit, combine it with all permitted combinations for counters of smaller size. This may result in a generator that produces a infinite number of combinations. So, we need to borrow from each generator evenly.
So gens is a list of generators. Think of this as a list of all counters starting with one digit: gens !! 0 is a list of all counters starting with 1, gens !! 1 is a list of all counters starting with 2, etc.
In order to borrow from each generator evenly, we could transpose the list of generators - that way we would get a list of first elements of the generators, followed by a list of second elements of the generators, etc.
Since the list of generators may be infinite, we cannot afford to transpose the list of generators, because we may never get to look at the second element of any generator (for a infinite number of digits we'd have a infinite number of generators). So, we enumerate the elements from the generators "diagonally" - take first element from the first generator; then take the second element from the first generator and the first from the second generator; then take the third element from the first generator, the second from the second, and the first element from the third generator, etc. This can be done by folding the list of generators with a function f, which zips together two lists - one list is the generator, the other is the already-zipped generators -, the beginning of one of them being offset by one step by adding []: to the head. This is almost zipWith (:) ys ([]:n) - the difference is that if n or ys is shorter than the other one, we don't drop the remainder of the other list. Note that folding with zipWith (:) ys n would be a transpose.
For this answer I will take "smallest" to refer to the sum of the numbers in the tuple.
To list all possible pairs in order, you can first list all of the pairs with a sum of 2, then all pairs with a sum of 3 and so on. In code
pairsWithSum n = [(i, n-i) | i <- [1..n-1]]
xs = concatMap pairsWithSum [2..]
Haskell doesn't have facilities for dealing with n-tuples without using Template Haskell, so to generalize this you will have to switch to lists.
ntuplesWithSum 1 s = [[s]]
ntuplesWithSum n s = concatMap (\i -> map (i:) (ntuplesWithSum (n-1) (s-i))) [1..s-n+1]
nums n = concatMap (ntuplesWithSum n) [n..]
Here's another solution, with probably another slightly different idea of "smallest". My order is just "all tuples with max element N come before all tuples with max element N+1". I wrote the versions for pairs and triples:
gen2_step :: Int -> [(Int, Int)]
gen2_step s = [(x, y) | x <- [1..s], y <- [1..s], (x == s || y == s)]
gen2 :: Int -> [(Int, Int)]
gen2 n = concatMap gen2_step [1..n]
gen2inf :: [(Int, Int)]
gen2inf = concatMap gen2_step [1..]
gen3_step :: Int -> [(Int, Int, Int)]
gen3_step s = [(x, y, z) | x <- [1..s], y <- [1..s], z <- [1..s], (x == s || y == s || z == s)]
gen3 :: Int -> [(Int, Int, Int)]
gen3 n = concatMap gen3_step [1..n]
gen3inf :: [(Int, Int, Int)]
gen3inf = concatMap gen3_step [1..]
You can't really generalize it to N-tuples, though as long as you stay homogeneous, you may be able to generalize it if you use arrays. But I don't want to tie my brain into that knot.
I think this is the simplest solution if "smallest" is defined as x+y+z because after you find your first solution in the space of Integral valued pythagorean triangles, your next solutions from the infinite list are bigger.
take 1 [(x,y,z) | y <- [1..], x <- [1..y], z <- [1..x], z*z + x*x == y*y]
-> [(4,5,3)]
It has the nice property that it returns each symmetrically unique solution only once. x and z are also infinite, because y is infinite.
This does not work, because the sequence for x never finishes, and thus you never get a value for y, not to mention z. The rightmost generator is the innermost loop.
take 1 [(z,y,x)|z <- [1..],y <- [1..],x <- [1..],x*x + y*y == z*z]
Sry, it's quite a while since I did haskell, so I'm going to describe it with words.
As I pointed out in my comment. It is not possible to find the smallest anything in an infinite list, since there could always be a smaller one.
What you can do is, have a stream based approach that takes the lists and returns a list with only 'valid' elements, i. e. where the condition is met. Lets call this function triangle
You can then compute the triangle list to some extent with take n (triangle ...) and from this n elements you can find the minium.

Haskell - get nth element without "!!"

I need to get the nth element of a list but without using the !! operator. I am extremely new to haskell so I'd appreciate if you can answer in more detail and not just one line of code. This is what I'm trying at the moment:
nthel:: Int -> [Int] -> Int
nthel n xs = 0
let xsxs = take n xs
nthel n xs = last xsxs
But I get: parse error (possibly incorrect indentation)
There's a lot that's a bit off here,
nthel :: Int -> [Int] -> Int
is technically correct, really we want
nthel :: Int -> [a] -> a
So we can use this on lists of anything (Optional)
nthel n xs = 0
What you just said is "No matter what you give to nthel return 0". which is clearly wrong.
let xsxs = ...
This is just not legal haskell. let ... in ... is an expression, it can't be used toplevel.
From there I'm not really sure what that's supposed to do.
Maybe this will help put you on the right track
nthelem n [] = <???> -- error case, empty list
nthelem 0 xs = head xs
nthelem n xs = <???> -- recursive case
Try filling in the <???> with your best guess and I'm happy to help from there.
Alternatively you can use Haskell's "pattern matching" syntax. I explain how you can do this with lists here.
That changes our above to
nthelem n [] = <???> -- error case, empty list
nthelem 0 (x:xs) = x --bind x to the first element, xs to the rest of the list
nthelem n (x:xs) = <???> -- recursive case
Doing this is handy since it negates the need to use explicit head and tails.
I think you meant this:
nthel n xs = last xsxs
where xsxs = take n xs
... which you can simplify as:
nthel n xs = last (take n xs)
I think you should avoid using last whenever possible - lists are made to be used from the "front end", not from the back. What you want is to get rid of the first n elements, and then get the head of the remaining list (of course you get an error if the rest is empty). You can express this quite directly as:
nthel n xs = head (drop n xs)
Or shorter:
nthel n = head . drop n
Or slightly crazy:
nthel = (head .) . drop
As you know list aren't naturally indexed, but it can be overcome using a common tips.
Try into ghci, zip [0..] "hello", What's about zip [0,1,2] "hello" or zip [0..10] "hello" ?
Starting from this observation, we can now easily obtain a way to index our list.
Moreover is a good illustration of the use of laziness, a good hint for your learning process.
Then based on this and using pattern matching we can provide an efficient algorithm.
Management of bounding cases (empty list, negative index).
Replace the list by an indexed version using zipper.
Call an helper function design to process recursively our indexed list.
Now for the helper function, the list can't be empty then we can pattern match naively, and,
if our index is equal to n we have a winner
else, if our next element is empty it's over
else, call the helper function with the next element.
Additional note, as our function can fail (empty list ...) it could be a good thing to wrap our result using Maybe type.
Putting this all together we end with.
nth :: Int -> [a] -> Maybe a
nth n xs
| null xs || n < 0 = Nothing
| otherwise = helper n zs
where
zs = zip [0..] xs
helper n ((i,c):zs)
| i == n = Just c
| null zs = Nothing
| otherwise = helper n zs

Resources