I think about the function to count all positives numbers in a list. My idee was
countPositives :: [Int] -> Int
countPositives xs = length [ x | x <- xs, x > 0]
That code work, but I thinking it is possible to write with the filter function or with guards. Is it possilbe and if yes, how can I write it?
Both approaches would be pretty straightforward.
Filter the collection and count it's length:
countPositives' :: [Int] -> Int
countPositives' = length.filter (>0)
With guards:
countPositives'' :: [Int] -> Int
countPositives'' [] = 0
countPositives'' (x:xs) | x > 0 = 1 + countPositives'' xs
| otherwise = countPositives'' xs
As yet another alternative, use a fold:
ghci> lst = [1, 2, 4, 7, -2, -3, 0, 8]
ghci> foldr (\x i -> if x > 0 then i + 1 else i) 0 lst
5
Related
--This line count how many 0 are in the list
hasZero :: [Int] -> Bool
hasZero x = 0 < sum [1 | y <- x, y == 0]
--In this line I want to count how many empty list are in the list, but I got compiling erorr.
hasEmpty :: [[a]] -> Bool
hasEmpty x = 0 < [1 | y <- [x], y == []]
There are 2 issues in your second method - you are missing sum which does the count in the first one, and you are wrapping passed list into another one, it should be y <- x as in the first one:
hasEmpty :: [[a]] -> Bool
hasEmpty x = 0 < sum [1 | y <- x, null y]
Which can be rewritten as:
hasEmpty :: [[a]] -> Bool
hasEmpty = any null
In the first example, you summed the elements of the list your list comprehension generated. In the second, you haven't done this. You also don't need to put x in brackets.
hasEmpty :: Eq a => [[a]] -> Bool
hasEmpty x = 0 < sum [1 | y <- x, y == []]
This is a peculiar way to accomplish this goal. The more idiomatic way (aside from using the existing Prelude function any) would be to use pattern matching and recursion.
hasZero :: [Int] -> Bool
hasZero [] = True
hasZero (0:_) = True
hasZero (_:xs) = hasZero xs
Using any:
hasZero :: [Int] -> Bool
hasZero = any (== 0)
Given two lists of digits such as [1, 2, 0] = 120 and [1,0,1] = 101, my function sub should return the list [1, 9] = 19 but the function is returning [2, -1] instead. How do I solve this carry problem? It works fine when there isn't a carry and it only receives positive numbers.
Here's the code I have:
sub_Carry :: Integer -> [Integer] -> [Integer] -> [Integer]
sub_Carry c x []
| c == 0 = x
| otherwise = sub_Carry 0 [c] x
sub_Carry c [] x
| c == 0 = x
| otherwise = sub_Carry 0 x [c]
sub_Carry c (x : xs) (y : ys) = (x - y) : sub_Carry c xs ys
sub :: [Integer] -> [Integer] -> [Integer]
sub op1 op2
| to_Integer(op1) == to_Integer(op2) = [0]
| to_Integer(op1) > to_Integer(op2) = drop_Zeros (reverse (sub_Carry 0 (reverse op1) (reverse op2)))
| otherwise = [-1] ++ drop_Zeros (reverse (sub_Carry 0 (reverse op1) (reverse op2)))
Other considerations:
I've have other utility functions such as to_Integer that converts the list into it's correspondent integer, drop_Zeros that removes zeros to the right of the list ([0, 1, 0] = [1, 0])
in the case the result is a negative number it should return the list with -1 at the head ([1, 0, 0] - [1, 0, 1] = [-1, 1])
I noticed that you don't use the parameter c for carrying. It is the central point of the exercise. It is also necessary to solve the case when the list of a parameter y ends earlier than x. My program works only for positive results. So I also modified the function sub to reverse parameters when op1 < op2. Now there should be always a positive result, which you then negate using the constant -1.
sub_Carry :: Integer -> [Integer] -> [Integer] -> [Integer]
sub_Carry 0 [] [] = []
sub_Carry c x [] = sub_Carry c x [0]
sub_Carry c (x : xs) (y : ys)
| (x - y - c) < 0 = (10 + x - y - c) : sub_Carry 1 xs ys
| otherwise = (x - y - c ) : sub_Carry 0 xs ys
sub :: [Integer] -> [Integer] -> [Integer]
sub op1 op2
| to_Integer(op1) == to_Integer(op2) = [0]
| to_Integer(op1) > to_Integer(op2) = drop_Zeros (reverse (sub_Carry 0 (reverse op1) (reverse op2)))
| otherwise = [-1] ++ drop_Zeros (reverse (sub_Carry 0 (reverse op2) (reverse op1)))
I want to write a function wp (without primes) which removes all the primes from a list
of numbers. Thus, wp [1, 2, 3, 4, 5, 6, 7] = [1, 4, 6].
I tried coding it like this:
wp :: [Int] -> [Int]
prime :: Int -> Bool
prime n = if f n > 0 then False else True
where f n = foldl (\acc x -> if n `mod` x == 0 then acc = acc + 1 else acc = acc + 0) 0 [2..n-1]
wp xs = filter (not.prime) xs
But when compiling it, I get the "parse error on input =" error but I can't find my syntax error. Any ideas?
Your problem is in the use of acc = acc + x. You just need to write it as acc + 1 or acc + 0 (or just acc really) instead. Also, I would recommend writing the function signature on top of the function definition, rather than a C-style list at the top.
Finally, I should note that wp will not include 1 in the result, so you will have to manually include it.
prime :: Int -> Bool
prime n = if f n > 0 then False else True
where f n = foldl (\acc x -> if n `mod` x == 0 then acc + 1 else acc) 0 [2..n-1]
wp :: [Int] -> [Int]
wp xs = 1 : filter (not.prime) xs
I'm trying to find out values between two numbers. So far I have:
heightbetween :: Float -> Float -> [Float] -> Int
heightbetween _ _ [] = 0
heightbetween n s (x:xs)
| (n < x) : (s > x) = 1 + (heightbetween n s xs)
| otherwise = heightbetween n s xs
you could filter the list of heights to the predicate of being between the upper and lower bound, and determine the length of the remaining list of elements:
filter :: (a -> Bool) -> [a] -> [a]
the first argument allows you to see whether a predicate is true or not. For example:
filter ((==) 0) [1, 2, 3, 0, 4, 1, 4, 0, 6, 2, 0]
will result in the list
[0, 0, 0, 0]
Determining the length of this list will show you how many elements satisfy your predicate.
I have written a function to compute the median value of a list
task3 xs | null xs = Nothing
| odd len = xs !! mid
| even len = evenMedian
where len = length xs
mid = len `div` 2
evenMedian = (xs !! mid + xs !! (mid+1)) / 2
I thought it is right and it also pass the load. But when I use the function, it did not work.
What is wrong here?
As Lee mentioned, the list must be sorted first.
(The median of [1,1,8,1,1] is 1 (not 8). so you have to sort it to [1,1,1,1,8] and then take the one in the middle).
The other thing is, that you return Nothing, so the other results have to be of type Maybe a too:
Just $ xs !! mid
Just evenMedian
You can use sort from Data.List to sort your list before applying it to task3.
Like so:
task xs = task3 (sort xs)
How about Median of Medians? Note that this computes only an approximation to the median.
Here is a Haskell implementation:
import Data.List
median :: Ord a => [a] -> a
median xs = select (length xs `div` 2) xs
select :: Ord a => Int -> [a] -> a
select i xs
| n <= 5
= sort xs !! i
| lengthLower == i
= medianOfMedians
| lengthLower < i
= select (i - lengthLower - 1) upperPartition
| otherwise
= select i lowerPartition
where
n = length xs
medianOfMedians = median (map median (chunksOf 5 xs))
(lowerPartition, _:upperPartition) = partition (< medianOfMedians) xs
lengthLower = length lowerPartition
chunksOf :: Int -> [a] -> [[a]]
chunksOf _ [] = []
chunksOf n xs
| (beginning, rest) <- splitAt n xs
= beginning : chunksOf n rest
Recursion could do the job also.
import Data.List
medianFromSorted :: Fractional a => [a] -> Maybe a
medianFromSorted [] = Nothing
medianFromSorted [a] = Just a
medianFromSorted [a,b] = Just ((a + b) / 2)
medianFromSorted (a:xs) = medianFromSorted (init xs) -- init is not efficient
median :: Ord a => Fractional a => [a] -> Maybe a
median = medianFromSorted . sort
My version of median for Integer
import Data.List (sort)
getMiddle [] = 0
getMiddle xs = (a' + b') `div` 2
where a' = head $ drop a xs
b' = head $ drop b xs
a = (n `div` 2)
b = n' - 1
n' = n `div` 2
n = length xs
median :: [Integer] -> Integer
median [] = 0
median xs = result
where result = if (n `mod` 2 == 0)
then getMiddle sorted
else head $ drop a sorted
a = (n - 1) `div` 2
n = length xs
sorted = sort xs
main = print $ median [1, 4, 5, 7, 9, 100]
-- 6
Even with kaan's answer, this code will still not produce a correct median. Another issue that has been overlooked is that Haskell lists are zero indexed. As a result, all of the code is correct with kaan's additions except
evenMedian = (xs !! mid + xs !! (mid+1)) / 2
which should actually be
evenMedian = (xs !! (mid - 1) + xs !! mid) / 2
Otherwise the result is incorrect. The wrong way produces task3 [1, 2, 3, 4] == Just 3.5, while the correct way produces task3 [1, 2, 3, 4] == Just 2.5