Element is in first half of the list, Haskell - haskell

Reading the book Get Programming with Haskell, one of the questions was to find if a given element is in the first half of a list. This can be done as
isInFirstHalf x xs = elem x firstHalf
where firstHalf = take (length xs `div` 2) xs
However, the problem is that here length traverses the whole list. In an imperative language, one can shortcircut the loop early by keeping track of the element index and the current counter. E.g. if the list has a million elements, and there was a match on the third element, once you finish looping through the sixth element, you can immediately return true.
My question is if there's a way to implement something like this in Haskell.

Sure.
halfAsLong (x:_:xs) = x:halfAsLong xs
halfAsLong _ = []
isInFirstHalf x xs = elem x (zipWith const xs (halfAsLong xs))
Try it out:
> isInFirstHalf 3 (1:2:3:4:5:6:undefined)
True
Exercises for the reader:
Where did the element index and current counter of your proposed imperative solution go? (They are still in there, just hidden in a way I think is a bit subtle!)
This rounds down when dividing odd lengths in half, like length xs `div` 2 does. How would the code have to change to round up, like (length xs + 1) `div` 2 does?

Daniel Wagner posted a very nice answer that shows that you don't really need indices, after all.
Still, if you do want to use indices, a solution can be crafted as follows.
We enumerate all the list elements by pairing them with their indices. This is done by using zip [0..] xs (or zip [1..] xs if you want to start counting at 1).
We find whether your x is in the list, and find its index i if it's present. One could proceed by direct recursion, or use something like dropWhile ((/= x) . fst) ... and then test the result.
Once we know i, we need to check whether there are at least i elements after that. This can be solved by direct recursion, or by dropping i-1 elements and testing whether the result is a non empty list.
There are other alternatives, of course. We could for instance skip enumerating elements with zip [0..] and use recursion by keeping track of the current index: foo n x (y:ys) = ... foo (n+1) x ys ....

Here’s another way to think of the task. An element x appears in the first half of a list xs, excluding the midpoint, if there are strictly fewer elements before the first occurrence of the element than after it.
We can write break (== x) xs using the standard function break :: (a -> Bool) -> [a] -> ([a], [a]) to split xs into two parts: those appearing before x (or all of xs, if x is not found), and the remainder (including x, if it is found).
> break (== 0) []
([], [])
> break (== 0) [0, 1]
([], [0, 1])
> break (== 0) [1, 0]
([1], [0])
> break (== 0) [1, 2, 0, 3, 4]
([1, 2], [0, 3, 4])
> break (== 0) [1, 2, 3, 4]
([1, 2, 3, 4], [])
We then want to compare the lengths of these two parts without calculating the actual lengths strictly as Int. To do so, we can compute the shape of each part by ignoring all its elements, using shape = map (const ()), a.k.a. void :: (Functor f) => f a -> f () specialised to lists.
shape :: [a] -> [()]
shape = void
The Ord instance for lists sorts them lexicographically, and all values of type () are equal—okay, the only value of type ()—so a comparison of shapes [()] is a comparison of the lengths of the lists, which is also lazy enough for our purposes. (For maximal laziness, shape could be defined as genericLength on a lazy natural number type like data N = Z | S N with an appropriate Ord instance.)
> [] < repeat ()
True
> shape [5 .. 10] >= shape [1 .. 3]
True
> shape [1 .. 3] > shape [1 ..]
False
We can also “decrement” the shape of a list using drop 1, which we’ll use to skip counting the element itself if it was found. (Alternatively, we could “increment” the shape with (() :).)
Finally, putting these elements together leads to a fairly simple solution:
isInFirstHalf :: (Eq a) => a -> [a] -> Bool
isInFirstHalf x xs = shape before < shape (drop 1 after)
where
(before, after) = break (== x) xs
Notice that if the element was not found, after will be empty, so drop 1 will have no effect, but the shape of before can’t possibly be smaller than the empty shape [], so the comparison (<) will still correctly return False.

Related

How to map a function taking two parameters (instead of one)?

I have a Haskell problem and I came up with a solution but I just can't put pen to paper.
Basically I have a function calc that takes in an Int and returns a Float.
calc :: Int -> Int -> Float
In my function g I want to apply this function on an array
g :: [Int] -> [Float]
Since calc takes two Int parameters I want to consume two Ints (
x being the first index of the array and x+1 being second index). This will keep repeating the function on (index of array) [1][2], [2][3], [3][4] etc.
g :: [Int] -> [Float]
g [] = ""
g (x:xs) = map calc x x+1
calc :: Int -> Int -> Float
calc current last = (current - last / last) * 100
I've tried to research online on how to use map and it basically said like this? Any idea why the code doesn't want to compile and if x+1 is even a viable?
Unary map is map but binary map is zipWith. So what's to zip together? The two copies of the same list, shifted by one position one against the other:
calc :: Int -> Int -> Float
g :: [Int] -> [Float]
g xs = zipWith calc xs (drop 1 xs)
This is all. The zipping automatically stops when the shorter sequence runs out.
zipWith foo applies foo to each pair of arguments, each argument coming from the corresponding list, one element after the other. It could be implemented using zip as
zipWith foo xs ys = map (\ (x,y) -> foo x y) $ zip xs ys
= [ foo x y | (x,y) <- zip xs ys ]
but it already does this by itself.
As an illustration, drop 1 [1,2,3] == [2,3] and this means that
zipWith calc [1, 2, 3] (drop 1 [1, 2, 3]) ==
zipWith calc [1, 2, 3]
[2, 3 ] ==
[calc 1
2,
calc 2
3]
You wanted to use indices. Indices are practically never used in Haskell with lists. We instead achieve the same effect by structural jiggling, and then when we advance along the two lists one element at a time, each operation is O(1) because the next element is already at the top of the advanced list. Whereas with the indices we'd have to traverse the same list from the top anew each time, leading to O(k) time per each one (kth) element, i.e. quadratic behavior overall.
update: taking the zipping approach leads to a possibility of code fusion,
g2 xs = zipWith calc xs (drop 1 xs)
= [calc x y | (x,y) <- zip xs (drop 1 xs)]
= [calc x y | (x:y:_) <- tails xs] -- tails ~= iterate (drop 1)
because why build a new structure to house the two consecutive elements when they already appear in a structure ... the original list structure.
Interestingly, Common Lisp has this special kind of map, a map on tails, as part of the language. While the regular map is known there as mapcar, the map on tails is known there as maplist (it's a map on non-empty tails, to be precise).
I think the best a solution is
-- Returns the empty list on empty list due to laziness of zip
g xs = uncurry calc `map` zip xs (tail xs)
-- | |- this is the list of pairs with indeces: [(1,2), (2,3), (3,4) ...]
-- |- this converts a two arguments functions on a function with single 2-tuple argument
EDIT: #Will Ness solution is actually better.

Concat operation returns empty list

module Sample where
lastPeg = 15
leftCol = [1, 2, 4, 7 , 11]
rightCol = [1, 3, 6, 10, 15]
rowData = []
makeRowData :: Integer-> Integer-> [Integer]
makeRowData row pos =
if (pos <= lastPeg) then
if (pos >= leftCol !! (fromIntegral row-1)) &&
(pos <= rightCol !! (fromIntegral row-1)) then
do
rowData ++ [row]
makeRowData row (pos + 1)
else
makeRowData (row+1) (pos)
else
rowData
What I am essentially trying to do is make a triangle-shaped vector
represented as a single vector. Given a position within the triangle
I want to return the row containing that position.
For example:
rowData [6] = 4 (Represented as the 7th position in the triangle)
desired result: rowData = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5]
actual result: rowData = []
What am I doing wrong? Thanks.
Your central issue is in this part of the code:
do
rowData ++ [row]
makeRowData row (pos + 1)
I wonder if someone explained the operator (++) :: [a] -> [a] -> [a] to you as “appends a list to another list”, giving you the impression that an expression like xs ++ ys modifies xs. The first problem is that this isn’t the case; in reality this operator returns a new list consisting of the two inputs concatenated together, e.g. in GHCi:
> xs = [1, 2, 3]
> ys = [4, 5]
> xs ++ ys -- Append the lists.
[1, 2, 3, 4, 5]
> xs -- The original lists aren’t modified.
[1, 2, 3]
> ys
[4, 5]
The second problem is that the do block here has misled you: it’s operating on lists, so it doesn’t do the sequencing like IO that you seem to expect. do notation can be used with lists because the list type has an instance of the Monad typeclass, but instead of sequencing like IO, the list Monad instance does iteration, exactly like a list comprehension.
A full tutorial on monads and do notation is beyond the scope of this answer, but for example, all of these are equivalent:
-- List comprehension:
[x * y | x <- [2, 3], y <- [3, 5]]
-- Equivalent ‘do’ notation:
do { x <- [2, 3]; y <- [3, 5]; pure (x * y) }
-- Desugared ‘do’ notation:
[2, 3] >>= (\ x -> [3, 5] >>= (\ y -> pure (x * y)))
-- Instances of ‘Monad’ & ‘Applicative’ for lists:
concatMap (\ x -> concatMap (\ y -> [x * y]) [3, 5]) [2, 3]
-- Result of all of the above:
[6, 10, 9, 15]
So what your do block is doing is iterating over the list rowData ++ [row], which is always the single element row, because rowData is always the empty list [], by its definition. = means equal! In that single “loop” iteration, there’s a recursive call to makeRowData, and these calls continue, counting up with the pos parameter until it reaches lastPeg, at which point the function returns rowData, which is, again, just another name for [].
There are simpler and more idiomatic ways to solve the problem, but for the sake of learning, if you want to make as small a modification as possible and keep essentially this same explicit recursive structure, then the general principle of the solution is this:
Add a helper function with an “accumulator” parameter that keeps track of your intermediate state
Call this function from makeRowData with the initial state
If necessary, perform some final processing on the result before returning it from makeRowData
For example:
makeRowData :: Integer -> Integer -> [Integer]
makeRowData initialRow initialPos
-- Start the “loop” with an initial ‘rowData’ of ‘[]’.
= makeRowDataHelper [] initialRow initialPos
makeRowDataHelper :: [Integer] -> Integer -> Integer -> [Integer]
makeRowDataHelper rowData row pos =
if (pos <= lastPeg) then
if (pos >= leftCol !! (fromIntegral row-1)) &&
(pos <= rightCol !! (fromIntegral row-1)) then
-- To “modify” the state for the next iteration,
-- recursively call ‘go’ with different values.
makeRowDataHelper (rowData ++ [row]) row (pos + 1)
else
makeRowDataHelper rowData (row+1) (pos)
else
-- To exit the iteration, just return a value.
rowData
I haven’t tested whether your logic is actually correct here, but at least this should help you get unstuck.
Beyond that, there are also a few performance and style improvements you could make here:
Appending linked lists with ++ is slow; each iteration of go above, ++ must traverse the entire left hand side to construct its result, and that argument grows with each recursive call, so this function ends up taking quadratic time O(n2) in the length of the input. That doesn’t matter so much for small lists like this, but quickly becomes too inefficient to use with larger inputs.
A common way to solve this is to instead prepend elements to the accumulator parameter using the “cons” operator (element : list) in reverse order instead of appending them (list ++ [element]), then reverse the result afterward if necessary, since this is only linear O(n).
Instead of if … then … else … at the top level of a definition, it’s generally considered more idiomatic to use guards, for example:
go rowData row pos
| pos > lastPeg
= rowData
| pos >= leftCol !! (fromIntegral row-1)
, pos <= rightCol !! (fromIntegral row-1)
= …
| otherwise
= …
You’re repeatedly using !! on lists, which also takes linear time O(n) in the value of the index to traverse the list. Consider using a different data structure, such as Data.Array or Data.Vector which have constant-time O(1) indexing, or a different algorithm that doesn’t require random-access indexing into the lists. (E.g. look into the replicate function.)

Getting the gcd of a list

I am new to Haskell, actually I just started, and I would like to get a small hint to the question I am about to ask.
I am currently trying to get the GCD of a given list. For example, having the list [3, 6, 9] it will return 3.
For the moment, I tought of the following aproach, am I going in a good direction?
let getGCD l = map (\x y -> gcd x y) l
Not quite, you don't want map but rather a fold. map will let you transform every element in the list uniformly, so you give it a local transformation a -> b and it gives you a global transformation ([a] -> [b]). This isn't really what you want.
As a quick primer on folds, there's a whole family of them which all let us express computations which we build up by repeatedly applying a function to an initial value, the next element and the list, and then repeating with the result of that application as the new initial value. So foldl' (+) 0 [1, 2, 3, 4] would so something like
foldl' (+) 0 [1, 2, 3, 4] ==>
foldl' (+) 1 [2, 3, 4] ==>
foldl' (+) 3 [3, 4] ==>
foldl' (+) 6 [4] ==>
foldl' (+) 10 [] ==> -- For empty lists we just return the seed given
10
Can you see how to slot your problem into this framework?
More hints
You want to take a list and compute a result which depends on every element of the list, something like
gcdAll :: [Int] -> Int
gcdAll l = foldl' step initial l
is closer to what you want where step takes the current gcd of the list you've processed so far and the next element of the list and returns the next value and initial is the value to start with (and what is returned if l is empty. Since there isn't really a sane value, I'd instead split this into
gcdAll :: [Int] -> Maybe Int
gcdAll [] = Nothing
gcdAll (h : rest) = Just $ foldl' step h rest
so that you correctly signal the possibility of failure, after all, what's the gcd of nothing?
Note that foldl' is imported from Data.List.
You can recursively use gcd on a list (essentially a fold implementation)
gcd' :: (Integral a) => [a] -> a
gcd' [] = 1
gcd' [x] = x
gcd' (x:xs) = gcd x (gcd' xs)
A GCD is a property of a pair of numbers. So, really, you want to look at pairs of numbers drawn from your list. Ultimately you want to end up with a single GCD for the entire list, but as a first step, you want pairs.
There's a widely-known trick for working with consecutive pairs:
f1 list = zipWith f2 list (tail list)
The zipWith function is a bit like map, but works with a pair of lists. In this case, the original list, and the tail of the original list. (Note that this fails if the list is empty.) If you replace f2 with your gcd function, you now have a new list which is the GCD of each consecutive pair of numbers. And this list is one element shorter than the original:
f1 [x, y, z, w] ==> [gcd x y, gcd y z, gcd z w]
So each time you apply f1 to a list, you get a new, shorter list of GCDs. Apply it enough times, and you should end up with just one element...
I just tackled this one and this would be the quickest, simplest
myGCDMultiple = foldr1 gcd
> myGCDMultiple [3,6,9]
3

Comparing List Elements in Haskell

I'm just learning Haskell and am kind of stuck.
I'd like to compare list elements and measure the difference between them and return the highest one.
Unfortunatly, I do not know how to approach that problem.
For usual, I'd just iterate the list and compare the neighbours but that does not seem to be the way to go in Haskell.
I already tried using map but as I said I do not really know how you can solve that problem.
I'd be thankful for every kind of advice!
Best wishes
Edit: My idea is to first zip all pairs like this pairs a = zip a (tail a). Then I'd like to get all differences (maybe with map?) and then just chose the highest one. I just can't handle the Haskell syntax.
I don't know what you mean by "measure the discrepancy" between list elements, but if you want to calculate the "largest" element in a list, you'd use the built-in maximum function:
maximum :: Ord a => [a] -> a
This function takes a list of values that can be ordered, so all numbers, chars, and strings, among others.
If you want to get the difference between the maximum value and the minimum value, you can use the similar function minimum, then just subtract the two. Sure, there might be a slightly faster solution whereby you only traverse the list once, or you could sort the list then take the first and last elements, but for most cases doing diff xs = maximum xs - minimum xs is plenty fast enough and makes the most sense to someone else.
So what you want to do is compute a difference between successive elements, not calculate the minimum and maximum of each element. You don't need to index directly, but rather use a handy function called zipWith. It takes a binary operation and two lists, and "zips" them together using that binary operation. So something like
zipWith (+) [1, 2, 3] [4, 5, 6] = [1 + 4, 2 + 5, 3 + 6] = [5, 7, 9]
It is rather handy because if one of the lists runs out early, it just stops there. So you could do something like
diff xs = zipWith (-) xs ???
But how do we offset the list by 1? Well, the easy (and safe) way is to use drop 1. You could use tail, but it'll throw an error and crash your program if xs is an empty list, but drop will not
diff xs = zipWith (-) xs $ drop 1 xs
So an example would be
diff [1, 2, 3, 4] = zipWith (-) [1, 2, 3, 4] $ drop 1 [1, 2, 3, 4]
= zipWith (-) [1, 2, 3, 4] [2, 3, 4]
= [1 - 2, 2 - 3, 3 - 4]
= [-1, -1, -1]
This function will return positive and negative values, and we're interested only in the magnitude, so we can then use the abs function:
maxDiff xs = ??? $ map abs $ diff xs
And then using the function I highlighted above:
maxDiff xs = maximum $ map abs $ diff xs
And you're done! If you want to be fancy, you could even write this in point-free notation as
maxDiff = maximum . map abs . diff
Now, this will in fact raise an error on an empty list because maximum [] throws an error, but I'll let you figure out a way to solve that.
As mentioned by bheklilr, maximum is the quick and easy solution.
If you want some of the background though, here's a bit. What we're trying to do is take a list of values and reduce it to a single value. This is known as a fold, and is possible with (among others) the foldl function, which has the signature foldl :: (a -> b -> a) -> a -> [b] -> a.
The (a -> b -> a) section of foldl is a function which takes two values and returns one of the first type. In our case, this should be our comparison function:
myMax :: Ord a => a -> a -> a
myMax x y | x > y = x
| otherwise = y
(note that Ord a is required so that we can compare our values).
So, we can say
-- This doesn't work!
myMaximum :: Ord a => [a] -> a
myMaximum list = foldl myMax _ list
But what is _? It doesn't make sense to have a starting value for this function, so we turn instead to foldl1, which does not require a starting value (instead it takes the first two values from the list). That makes our maximum function
myMaximum :: Ord a => [a] -> a
myMaximum list = foldl1 myMax list
or, in pointfree format,
myMaximum :: Ord a => [a] -> a
myMaximum = foldl1 myMax
If you look at the actual definition of maximum in Data.List, you'll see it uses this same method.
map maps a function over a list. It transforms each thing1 in a list to a thing2.
What you want is to find the biggest difference between two neighbours, which you can't do with map alone. I'll assume you're only looking at numbers for now, because that's just easier.
diffs :: (Num a) => [a] -> [a]
diffs [] = []
diffs [x] = []
diffs (x1:x2:xs) = abs(x1-x2) : (diffs$x2:xs)
mnd :: (Num a, Ord a) => [a] -> a
mnd [] = 0
mnd [x] = 0
mnd xs = maximum$diffs xs
So diffs takes each list item one at a time and gets the absolute difference between it and its neighbour, then puts that at the front of a list it creates at it goes along (the : operator puts an individual element at the front of a list).
mnd is just a wrapper around maximum$diffs xs that stop exceptions being thrown.

Find max element and index of a list in Haskell

I'm taking my first steps into the wonderful world of Haskell. As an exercise, I would like to implement a method which finds the maximum element of a list and its index. Let's call this function "maxi". Calling maxi on a list should return the following result:
ghci> maxi [1, 3, 4, 1, 2, 3]
(4, 2)
4 is the largest int in this list, and it is located at index 2.
I have attempted to implement this function as follows:
maxim :: (Ord a) => [a] -> (a, Int)
maxim l =
let pmaxim :: (Ord a) => [a] -> Int -> (a, Int) -- Internal function to do the work
pmaxim [] _ = error "Empty list" -- List is empty, error
pmaxim [x] xi = (x, xi) -- List has one item, return it and the index
pmaxim (x:xs) xi -- More than one item, break list apart
| x > t = (x, xi) -- If current item is bigger, return it and its index
| otherwise = (t, ti) -- If list tail has a bigger item, return that
where (t, ti) = pmaxim xs (ti + 1) -- Get max of tail of the list
in pmaxim l 0 -- Call internal function with start index
When I call this, I get something really weird: ghci seems to hang after returning the max element's value.
ghci> maxi [1, 3, 4, 1, 2, 3]
(4,
I will venture a guess that this has something to do with Haskell's lazy evaluation nature, but I'm finding it difficult to figure out what is actually going on here, and how to fix it. I would also be really grateful for any tips anyone might have about how to debug in Haskell. Is there an easy way to print out values during execution without effecting behavior?
I just wanted to point out that I am aware that there are several better ways to get this behavior using built-in Haskell functions. I am implementing this from scratch to try and learn Haskell.
Thank you
It's because of a slight bug in your code. You have:
where (t, ti) = pmaxim xs (ti + 1)
... but it should actually be:
where (t, ti) = pmaxim xs (xi + 1)
This fixes your code, which now produces the correct solution:
>>> maxim [1, 2, 3, 2, 1]
(3, 2)
Your code hanged because your computation for ti results in an endless loop since you accidentally defined it in terms of itself. Note that ghc is a sufficiently smart compiler and figures out that t does not depend on the value of ti, which is why your version could still successfully compute the maximum value even if it cannot compute the index.
The standard way to debug pure computations is the Debug.Trace module.
As a side note, there is a much simpler solution:
import Data.List
import Data.Ord
maxi xs = maximumBy (comparing fst) (zip xs [0..])
Edit: Oops, I didn't see that you were deliberately implementing it from scratch, but I'll still leave that there.
I see you already got your question answered. I managed to do it without recursion, using lambda functions.
maxim xs = foldr (\ (x,y) acc -> if (x == maximum xs) then (x,y) else acc) (0,head xs) (zip xs [0..])

Resources