I'm trying to learn Haskell through this course, and I'm a bit stuck with the last assignment in the first module. The problem statement sounds as follows:
Write a function that takes a number and a list of numbers and returns a string, saying how many elements of the list are strictly greater than the given number and strictly lower.
lowerAndGreater 3 [1 .. 9] "3 is greater than 2 elements and lower than 6 elements"
Explanation: the list [1 .. 9] contains 9 elements: [1, 2, 3, 4, 5, 6, 7, 8, 9] The given number 3 is greater than 2 elements (1 and 2) and lower than 6 elements (4, 5, 6, 7, 8 and 9).
🕯 HINT: Use recursion to implement this function.
Here is my attempt to solve the problem:
lowerAndGreater :: Int -> [Int] -> String
lowerAndGreater n list = show(n) ++ " is greater than " ++ show(lesserThanN n list) ++ " elements and lower than " ++ show(greaterThanN n list) ++ " elements"
where
greaterThanN :: Int -> [Int] -> Int
greaterThanN greater l =
if null l
then greater
else if head l > n
then greaterThanN (greater + 1) (tail l)
else greaterThanN greater (tail l)
lesserThanN :: Int -> [Int] -> Int
lesserThanN lesser l =
if null l
then lesser
else if head l < n
then lesserThanN (lesser + 1) (tail l)
else lesserThanN lesser (tail l)
Unfortunately, the execution results aren't what I expect, e.g.
lowerAndGreater 3 [1 .. 9]
"3 is greater than 5 elements and lower than 9 elements"
Could you please advice where my mistake is?
It might be better to enumerate over the list a single time. We can do this with a function that returns a 2-tuple with:
import Control.Arrow (first, second)
lowerAndGreater :: Ord a => a -> [a] -> (Int, Int)
lowerAndGreater y = foldr go (0, 0)
where
go x
| x < y = first (+ 1)
| x > y = second (+ 1)
| otherwise = id
This then gives us:
ghci> lowerAndGreater 3 [1 .. 9]
(2,6)