Check if tuple list is in increasing consecutive order in Haskell - list

So I have a problem where I need to see if a list of positions which are in the form of (x,y) are in increasing consecutive order.
Just a for an example of whats meant to happen
[(1,2), (1,3), (1,4), (1,5), (1,6)] it would return True, but
[(1,2), (1,3), (1,5), (1,6), (1,7)] will return False
For example starting off like this.
is_in_order :: [Position] -> Bool
Thanks for the help.

As this seems to be an exercise example I will only provide some hints and not a full solution:
for just checking if all second tuples are consecutive a simple
checkConsecutive :: Num a => [a] -> Bool
checkConsecutive x = and $ zipWith (\x y -> y - x == 1) x (drop 1 x)
but I guess the case at hand should be more general - your inOrder function already provides a good base line
isConsecutive :: Num a => [a] -> Bool
isConsecutive [] = True
isConsecutive [x] = True
isConsecutive (x:y:xs) = consecutive x y && isConsecutive (y:xs)
where consecutive :: (Num a, Num b) => (a,b) -> (a,b) -> Bool
consecutive (x1,y1) (x2,y2) = ..
You write that you need case in order to do that, you can use a case expression in consecutive, but I don't think it would make the function clearer.
Note: you can simplify the function above to
isConsecutive (x:y:xs) = consecutive x y && isConsecutive (y:xs)
where consecutive :: (Num a, Num b) => (a,b) -> (a,b) -> Bool
consecutive (x1,y1) (x2,y2) = ..
isConsecutive _ = True
the _ indicates a "catchall" pattern - i.e. it matches anything that is not matching the above patterns.
So the remaining task is to declare what it means for two tuples to be consecutive.

You can implement isInOrder this way:
isInOrder xs = all check $ zip xs $ tail xs where
check ((x1,y1),(x2,y2)) = x1<=x2 && y2-y1==1
You can modify check function the way you mean 'increasing consecutive order'

Related

Haskell error when trying to get the last element

So, I am trying to implement a function that, given a list of 3 elements ((Int,Int),Int), returns True when on the second position is the same value for all 3 and False otherwise.
For instance, [((1,2),7),((5,3),7),((1,9),7)] should return True and [((1,2),3),((5,3),3),((1,9),5)] should return False.
Here is my code:
bc :: [((Int,Int),Int)]
wcheck :: [((Int,Int),Int)] -> Bool
wcheck bc
| (( fst(fst bc) == fst(snd bc) ) && ( fst(snd bc) == fst(last bc) )) = True
| otherwise = False
And the error that I get:
E:\\study related\Module1\week 4\ttt.hs:55:65: error:
* Couldn't match expected type `[(a, b0)]'
with actual type `((a, b), (a, b1))'
* In the first argument of `last', namely `bc'
In the first argument of `fst', namely `(last bc)'
In the second argument of `(==)', namely `fst (last bc)'
* Relevant bindings include
bc :: ((a, b), (a, b1))
(bound at E:\\study related\Module1\week 4\ttt.hs:54:8)
wcheck :: ((a, b), (a, b1)) -> Bool
(bound at E:\\study related\Module1\week 4\ttt.hs:54:1)
|
55 | | (( fst(fst bc) == fst(snd bc) ) && ( fst(snd bc) == fst(last bc) )) = True
|
Could you please tell me why I get this error and a way to fix it? Thank you.
It will probably be easier if we perform simple pattern matching instead of using fst :: (a, b) -> a, etc.
Second item of the first item of the tuple
We can use a pattern ((_, x), _) to obtain the second element from such 2-tuple wrapped in a 2-tuple.
So we can use pattern matching like:
wcheck :: [((Int,Int),Int)] -> Bool
wcheck [((_, x), _), ((_, y), _), ((_, z), _)] = x == y && y == z
wcheck _ = False
So here if the list contains three elements, we unpack the elements, and then check if the "second item"s are equal to each other. In case the pattern does not match (for a list with too few, or too much elements), we just return False.
But a "list of three elements" does not make much sense. In case the number of elements is known at compile time, it is better to use a tuple, since in that way, the compiler can verify that you can only provide 3-tuples to that function.
Second item of the tuple
In case we are interested in the second item of the tuple, we can use (_, x) as pattern (we are not interested in the first item whatsoever):
wcheck :: [((Int,Int),Int)] -> Bool
wcheck [(_, x), (_, y), (_, z)] = x == y && y == z
wcheck _ = False
Note that we can generalize the signature with:
wcheck :: Eq c => [((a, b), c)] -> Bool
wcheck [(_, x), (_, y), (_, z)] = x == y && y == z
wcheck _ = False
fst and snd are not very nice in this situation. We can extract the bit we care about by doing a pattern match:
let (_,y) = x in ...
Now you want to do that to each element of your list (to check that every element has the same second value):
map (\(_,x) -> x)
And then you want to check that they are all equal:
allEqual :: Eq a => [a] -> Bool
allEqual [] = True
allEqual (x:xs) = all (\y->x==y) xs
This gets the first element, x, from a list (if it exists) and checks that ever other item y satisfies the test that x==y
So we can now write your function:
wcheck xs = allEqual (map (\(_,y) -> y) xs)
Given that you want to test the equality of the second element of the outer pair, there are so many ways to do this, including the following.
First, fmapping snd gives you these elements:
λ> fmap snd [((1,2),7),((5,3),7),((1,9),7)]
[7,7,7]
Now you can group them to lists of consecutive equal numbers:
λ> import Data.List
λ> (group . fmap snd) [((1,2),7),((5,3),7),((1,9),7)]
[[7,7,7]]
The values are equal if the length of this list of lists is at most one (assuming an empty list of such pairs is defined to have equal second elements):
λ> (length . group . fmap snd) [((1,2),7),((5,3),7),((1,9),7)]
1
Putting these together we can define
import Data.List
equalSnds :: Eq a => [(b, a)] -> Bool
equalSnds xs = (length . group . fmap snd) xs <= 1
So that
λ> equalSnds [((1,2),7),((5,3),7),((1,9),7)]
True
λ> equalSnds [((1,2),3),((5,3),3),((1,9),5)]
False
If you want to also test for the length of the list, you can do it separately:
wcheck :: [((Int,Int),Int)] -> Bool
wcheck xs = length xs == 3 && equalSnds xs

haskell: how to get list of numbers which are higher then their neighbours in a starting list

I am trying to learn Haskell and I want to solve one task. I have a list of Integers and I need to add them to another list if they are bigger then both of their neighbors. For Example:
I have a starting list of [0,1,5,2,3,7,8,4] and I need to print out a list which is [5, 8]
This is the code I came up but it returns an empty list:
largest :: [Integer]->[Integer]
largest n
| head n > head (tail n) = head n : largest (tail n)
| otherwise = largest (tail n)
I would solve this as outlined by Thomas M. DuBuisson. Since we want the ends of the list to "count", we'll add negative infinities to each end before creating triples. The monoid-extras package provides a suitable type for this.
import Data.Monoid.Inf
pad :: [a] -> [NegInf a]
pad xs = [negInfty] ++ map negFinite xs ++ [negInfty]
triples :: [a] -> [(a, a, a)]
triples (x:rest#(y:z:_)) = (x,y,z) : triples rest
triples _ = []
isBig :: Ord a => (a,a,a) -> Bool
isBig (x,y,z) = y > x && y > z
scnd :: (a, b, c) -> b
scnd (a, b, c) = b
finites :: [Inf p a] -> [a]
finites xs = [x | Finite x <- xs]
largest :: Ord a => [a] -> [a]
largest = id
. finites
. map scnd
. filter isBig
. triples
. pad
It seems to be working appropriately; in ghci:
> largest [0,1,5,2,3,7,8,4]
[5,8]
> largest [10,1,10]
[10,10]
> largest [3]
[3]
> largest []
[]
You might also consider merging finites, map scnd, and filter isBig in a single list comprehension (then eliminating the definitions of finites, scnd, and isBig):
largest :: Ord a => [a] -> [a]
largest xs = [x | (a, b#(Finite x), c) <- triples (pad xs), a < b, c < b]
But I like the decomposed version better; the finites, scnd, and isBig functions may turn out to be useful elsewhere in your development, especially if you plan to build a few variants of this for different needs.
One thing you might try is lookahead. (Thomas M. DuBuisson suggested a different one that will also work if you handle the final one or two elements correctly.) Since it sounds like this is a problem you want to solve on your own as a learning exercise, I’ll write a skeleton that you can take as a starting-point if you want:
largest :: [Integer] -> [Integer]
largest [] = _
largest [x] = _ -- What should this return?
largest [x1,x2] | x1 > x2 = _
| x1 < x2 = _
| otherwise = _
largest [x1,x2,x3] | x2 > x1 && x2 > x3 = _
| x3 > x2 = _
| otherwise = _
largest (x1:x2:x3:xs) | x2 > x1 && x2 > x3 = _
| otherwise = _
We need the special case of [x1,x2,x3] in addition to (x1:x2:x3:[]) because, according to the clarification in your comment, largest [3,3,2] should return []. but largest [3,2] should return [3]. Therefore, the final three elements require special handling and cannot simply recurse on the final two.
If you also want the result to include the head of the list if it is greater than the second element, you’d make this a helper function and your largest would be something like largest (x1:x2:xs) = (if x1>x2 then [x1] else []) ++ largest' (x1:x2:xs). That is, you want some special handling for the first elements of the original list, which you don’t want to apply to all the sublists when you recurse.
As suggested in the comments, one approach would be to first group the list into tuples of length 3 using Preludes zip3 and tail:
*Main> let xs = [0,1,5,2,3,7,8,4]
*Main> zip3 xs (tail xs) (tail (tail xs))
[(0,1,5),(1,5,2),(5,2,3),(2,3,7),(3,7,8),(7,8,4)]
Which is of type: [a] -> [b] -> [c] -> [(a, b, c)] and [a] -> [a] respectively.
Next you need to find a way to filter out the tuples where the middle element is bigger than the first and last element. One way would be to use Preludes filter function:
*Main> let xs = [(0,1,5),(1,5,2),(5,2,3),(2,3,7),(3,7,8),(7,8,4)]
*Main> filter (\(a, b, c) -> b > a && b > c) xs
[(1,5,2),(7,8,4)]
Which is of type: (a -> Bool) -> [a] -> [a]. This filters out elements of a list based on a Boolean returned from the predicate passed.
Now for the final part, you need to extract the middle element from the filtered tuples above. You can do this easily with Preludes map function:
*Main> let xs = [(1,5,2),(7,8,4)]
*Main> map (\(_, x, _) -> x) xs
[5,8]
Which is of type: (a -> b) -> [a] -> [b]. This function maps elements from a list of type a to b.
The above code stitched together would look like this:
largest :: (Ord a) => [a] -> [a]
largest xs = map (\(_, x, _) -> x) $ filter (\(a, b, c) -> b > a && b > c) $ zip3 xs (tail xs) (tail (tail xs))
Note here I used typeclass Ord, since the above code needs to compare with > and <. It's fine to keep it as Integer here though.

Haskell Function that Takes A Pair of Values and a List

My homework has been driving me up the wall. I am supposed to write a function called myRepl that takes a pair of values and a list and returns a new list such that each occurrence of the first value of the pair in the list is replaced with the second value.
Example:
ghci> myRepl (2,8) [1,2,3,4]
> [1,8,3,4].
So far I have something like this (but its very rough and not working well at all. I need help with the algorithm:
myRep1 (x,y) (z:zs) =
if null zs then []
else (if x == z then y : myRep1 zs
else myRep1 zs )
I don't know how to create a function that takes a pair of values and a list. I'm not sure what the proper syntax is for that, and I'm not sure how to go about the algorithm.
Any help would be appreciated.
How about something like:
repl (x,y) xs = map (\i -> if i==x then y else i) xs
Explanation
map is a function that takes a function, applies it to each value in the list, and combines all the return values of that function into a new list.
The \i -> notation is a shortcut for writing the full function definition:
-- Look at value i - if it's the same as x, replace it with y, else do nothing
replacerFunc x y i = if x == y then y else i
then we can rewrite the repl function:
repl (x, y) xs = map (replacerFunc x y) xs
I'm afraid the map function you just have to know - it is relatively easy to see how it works. See the docs:
http://www.haskell.org/hoogle/?hoogle=map
How to write this without map? Now, a good rule of thumb is to get the base case of the recursion out of the way first:
myRep1 _ [] = ???
Now you need a special case if the list element is the one you want to replace. I would recommend a guard for this, as it reads much better than if:
myRep1 (x,y) (z:zs)
| x == z = ???
| otherwise = ???
As this is home work, I left a few blanks for you to fill in :-)
myRepl :: Eq a => (a, a) -> [a] -> [a]
myRepl _ [] = []
myRepl (v, r) (x : xs) | x == v = r : myRepl (v, r) xs
| otherwise = x : myRepl (v, r) xs
Untupled arguments, pointfree, in terms of map:
replaceOccs :: Eq a => a -> a -> [a] -> [a]
replaceOccs v r = map (\ x -> if x == v then r else x)

haskell all function

I need a program that checks if the difference between all pairs of elements is in the interval from -2 up to 2 ( >= -2 && < 2). If it is, then return True, else return False. Foe example, [1,2,3] is True, but [1,3,4] is False.
I am using the all function. What is wrong with my if clause?
allfunc (x : xs)
= if all (...) xs
then allfunc xs
else [x] ++ allfunc xs
allfunc _
= []
Or I am doing something completely wrong?
For this, it's probably easier to use list comprehensions or do-notation.
pairsOf lst = do
x <- lst
y <- lst
return (x, y)
pairsOf returns the list of pairs of numbers in the input lst. For example, pairsOf [1,2,3] results in [(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)].
Now, you can define the difference between a pair in a one-liner \(x, y) -> x - y and map that over the list:
differences lst = map (\(x, y) -> x - y) (pairsOf lst)
Now you just have to make sure that each element in differences lst is between -2 and 2.
Of course, this is just one possible way to do it. There are many other ways as well.
The naive way to do what you describe is:
allfunc xs = all (<=2) [abs(a-b) | a <- xs, b <- xs ]
However, a more efficient method would be to compare the minimum and maximum of the list:
fastfunc [] = true
fastfunc xs = maximum xs - minimum xs <= 2
Why not simply...
allfunc xs = (maximum xs - minimum xs) <= 2
Or if you really want to investigate every pair, you can use monads:
import Control.Monad
allfunc xs = all ((<=2).abs) $ liftM2 (-) xs xs
liftA2 from Control.Applicative would do as well.
Well, the problem specification isn't very clear.
You say:
the diffence between all elements is in interval from -2 till 2 ( >= -2 && < 2)
But also:
Foe example, [1,2,3] is True, but [1,3,4] is False
How is it True for [1,2,3]?
Assuming you mean -2 <= diff <= 2, then I would use this:
allfunc :: (Ord a, Num a) => [a] -> Bool
allfunc theList = all (\x -> (x >= -2) && (x<2)) [x-y | x <- theList, y <- theList ]
allfunc [1,2,3] -- => True
allfunc [1,3,4] -- => False
Basically, yes you're doing something wrong. all is meant to take a predicate and a list of values to test. So it will return True if and only if all values yield true when applied to the given predicate function. I.e.:
allValuesEven = all even
allValuesOdd = all odd

Searching through list

I've been trying to define a function which, given a list of Integers and an Integer n, returns a Boolean indicating whether n occurs exactly once in the list.
I have this, but it is not working and I cannot figure it out
once :: [a] -> (a -> Bool) -> Bool
filter _ [] = []
filter p (x:xs)
| p x = x : filter p xs
| otherwise = filter p xs
An example of what I want would be:
Main> once [2,3,2,4] 2
False
Main> once [1..100] 2
True
As I thought my former solution was ugly, I asked in another forum and got this as answer:
once :: Eq a => a -> [a] -> Bool
once x = (== [x]) . filter (== x)
I think you can't write that function much nicer, and in contrast to the accepted answer it's lazy.
once :: (Eq a) => [a] -> a -> Bool
once xs x = (== 1) $ length $ filter (== x) xs
Well, you can filter the list, then see how many elements are in the resulting filter, right?
To get you started:
> filter (== 2) [1,2,3,4,5]
[2]
> filter (== 2) [1,2,3,4,5,2,2]
[2,2,2]
And to fold your list down to a Bool value, here, an example where we test if a list has three elements, returning a Bool:
> isThree (a:b:c:[]) = True
> isThree _ = False
So it is just a short matter of composing such functions:
> isThree . filter (==2)
or your variant (e.g. matching for lists of length 1).
Here is another version:
once x = not . (\xs -> null xs || x `elem` tail xs) . dropWhile (/= x)
--lambda hater version
import Control.Applicative
once x = not . ((||) <$> null <*> (elem x).tail) . dropWhile (/= x)
Of course it can't deal with infinite lists that contain zero or one x, but at least it terminates in case of more than one occurrence of x.