How to check in a tuple if element matches? - haskell

I am trying to check whether my second part of my tuple is 1.0 and if it is then I am storing it in the list. But I can't figure out how to implement the check.
number :: [(Integer, Double)] -> [Integer]
number lst = number' lst []
where
number' [] a = a
((mat,1.0): xs) a = number'(xs) (mat:a) -- Here I am getting my error
((_,lst): xs) a = number'(xs) a
Maybe someone has an idea.

The reason this doesn't work is because you need to write number' for every line:
number :: [(Integer, Double)] -> [Integer]
number lst = number' lst []
where
number' [] a = a
number' ((mat,1.0): xs) a = number'(xs) (mat:a)
number' ((_,lst): xs) a = number'(xs) a
But this will return the "keys" in reverse.
You can pattern match with:
number :: (Eq a, Num a) => [(a, b)] -> [a]
number ((x, 1):xs) = x : number xs
number (_:xs) = number xs
number [] = []
You can however work with list comprehension:
number :: (Eq a, Num a) => [(a, b)] -> [a]
number xs = [ x | (x, 1) <- xs ]
or with a combination of map and filter:
number :: (Eq a, Num a) => [(a, b)] -> [a]
number = map fst . filter ((1 ==) . snd)

Related

Get duplicated elements in a list without using (Ord a)

I have been trying to make a function that concatenates a list of lists, sorts it, and gives back the duplicated values.
The issue I'm facing is that it tells me to change (Eq a) to (Ord a) for the last function, but I cannot do this. How can I solve this without changing (Eq a) to (Ord a) ?
This is the code I have:
group :: Eq a => [a] -> [[a]]
group = groupBy (==)
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy _ [] = []
groupBy eq (x:xs) = (x:ys) : groupBy eq zs
where (ys,zs) = span (eq x) xs
uniq :: Eq b => [b] -> [b]
uniq = map head . group
insert :: Ord a => a -> [a] -> [a]
insert x [] = [x]
insert x (y:ys) | x < y = x:y:ys
| otherwise = y:(insert x ys)
isort :: (Eq a, Ord a) => [a] -> [a]
isort [] = []
isort (x:xs) = insert x (isort xs)
kms :: Ord a => [a]
kms xss = uniq (isort (concat xss))
pairwiseIntersections :: (Eq a) => [[a]] -> [a]
pairwiseIntersections xss = kms xss
You cannot sort a list without its elements having some ordering -- meaning that they must be instances of Ord.
You can do other things to deduplicate a list, like nub, but if you want it sorted you need Ord or an equivalent ordering.
You mention no complexity requirements, so the simplest approach could be
keepOnlyDups [] = []
keepOnlyDups (x:xs) = [x | elem x xs] ++ keepOnlyDups [ y | y <- xs, y /= x]
removeExtras [] = []
removeExtras (x:xs) = [x] ++ removeExtras [ y | y <- xs, y /= x]
answering both your question's text and the implied meaning of the code.
Implementing keepOnlyUniques is left as an exercise, if you're interested in that.

Every second element from list

I am trying to print every second element from list of lists
fun [[1,2,3],[4,5,6],[6,7,8]] = [2,5,7]
I have this:
fun xs = fmap head xs
but this returns every first elem from lists
I Just changed the output to [Maybe a] because using just fmap or map with head.tail cant handle the exception of shorter lists.
Also I generalized to N'th index:
takeNthIndex :: (Eq t, Num t) => t -> [a] -> Maybe a
takeNthIndex _ [] = Nothing
takeNthIndex 0 (x:xs) = Just x
takeNthIndex n (x:xs) = takeNthIndex (n-1) xs
everyNthIndex :: (Eq t, Num t) => t -> [[a]] -> [Maybe a]
everyNthIndex _ [] = []
everyNthIndex n (x:xs) = takeNthIndex n x : everyNthIndex n xs
everyNthIndexByMap :: (Eq t, Num t) => t -> [[a]] -> [Maybe a]
everyNthIndexByMap n = map (takeNthIndex n)
Usage:
everyNthIndex 1 [[1,2,3],[4,5,6],[6,7,8], []]
-- output: [Just 2,Just 5,Just 7,Nothing]
everyNthIndex is the recursive version of everyNthIndexByMap

How to remove second largest element in a list in haskell?

I have created a program to remove first smallest element but I dont how to do for second largest:
withoutBiggest (x:xs) =
withoutBiggestImpl (biggest x xs) [] (x:xs)
where
biggest :: (Ord a) => a -> [a] -> a
biggest big [] = big
biggest big (x:xs) =
if x < big then
biggest x xs
else
biggest big xs
withoutBiggestImpl :: (Eq a) => a -> [a] -> [a] -> [a]
withoutBiggestImpl big before (x:xs) =
if big == x then
before ++ xs
else
withoutBiggestImpl big (before ++ [x]) xs
Here is a simple solution.
Prelude> let list = [10,20,100,50,40,80]
Prelude> let secondLargest = maximum $ filter (/= (maximum list)) list
Prelude> let result = filter (/= secondLargest) list
Prelude> result
[10,20,100,50,40]
Prelude>
A possibility, surely not the best one.
import Data.Permute (rank)
x = [4,2,3]
ranks = rank (length x) x -- this gives [2,0,1]; that means 3 (index 1) is the second smallest
Then:
[x !! i | i <- [0 .. length x -1], i /= 1]
Hmm.. not very cool, let me some time to think to something better please and I'll edit my post.
EDIT
Moreover my previous solution was wrong. This one should be correct, but again not the best one:
import Data.Permute (rank, elems, inverse)
ranks = elems $ rank (length x) x
iranks = elems $ inverse $ rank (length x) x
>>> [x !! (iranks !! i) | i <- filter (/=1) ranks]
[4,2]
An advantage is that this preserves the order of the list, I think.
Here is a solution that removes the n smallest elements from your list:
import Data.List
deleteN :: Int -> [a] -> [a]
deleteN _ [] = []
deleteN i (a:as)
| i == 0 = as
| otherwise = a : deleteN (i-1) as
ntails :: Int -> [a] -> [(a, Int)] -> [a]
ntails 0 l _ = l
ntails n l s = ntails (n-1) (deleteN (snd $ head s) l) (tail s)
removeNSmallest :: Ord a => Int -> [a] -> [a]
removeNSmallest n l = ntails n l $ sort $ zip l [0..]
EDIT:
If you just want to remove the 2nd smallest element:
deleteN :: Int -> [a] -> [a]
deleteN _ [] = []
deleteN i (a:as)
| i == 0 = as
| otherwise = a : deleteN (i-1) as
remove2 :: [a] -> [(a, Int)] -> [a]
remove2 [] _ = []
remove2 [a] _ = []
remove2 l s = deleteN (snd $ head $ tail s) l
remove2Smallest :: Ord a => [a] -> [a]
remove2Smallest l = remove2 l $ sort $ zip l [0..]
It was not clear if the OP is looking for the biggest (as the name withoutBiggest implies) or what. In this case, one solution is to combine the filter :: (a->Bool) -> [a] -> [a] and maximum :: Ord a => [a] -> a functions from the Prelude.
withoutBiggest l = filter (/= maximum l) l
You can remove the biggest elements by first finding it and then filtering it:
withoutBiggest :: Ord a => [a] -> [a]
withoutBiggest [] = []
withoutBiggest xs = filter (/= maximum xs) xs
You can then remove the second-biggest element in much the same way:
withoutSecondBiggest :: Ord a => [a] -> [a]
withoutSecondBiggest xs =
case withoutBiggest xs of
[] -> xs
rest -> filter (/= maximum rest) xs
Assumptions made:
You want each occurrence of the second-biggest element removed.
When there is zero/one element in the list, there isn't a second element, so there isn't a second-biggest element. Having the list without an element that isn't there is equivalent to having the list.
When the list contains only values equivalent to maximum xs, there also isn't a second-biggest element even though there may be two or more elements in total.
The Ord type-class instance implies a total ordering. Otherwise you may have multiple maxima that are not equivalent; otherwise which one is picked as the biggest and second-biggest is not well-defined.

Finding max list within a list

I was trying to get the list with the greatest sum within a list and then return that list. But when I call the function with
max_list [[1,2],[3,6],[10,34,5]]
it gives me the error:
Exception: a4.hs:65:1-64: Non-exhaustive patterns in function max_list
This is the code:
max_num :: [Int] -> Int
max_num [x] = x
max_num (x:xs) | (max_num xs) > x = maxVal xs
| otherwise = x
max_list :: [[Int]] -> [Int]
max_list [[a]] = head(filter (\x -> (sum_int x) == (max_num [[a]]) [[a]])
My logic is as follows:
I will
Sum the elements in the sublist
Compare that element to see if it equals the max-value of the list
Filter out the values that do not equal the max-value
Example call:
head (filter (\x -> (sum x) == 11) [[1,3],[4,7],[2,5]])
> [4,7]
So in that case I calculated the value 11 before hand and its sum of each element is [4, 11, 7] and it will give me the value whose sum is equal to the max value
There is a function in Data.List called maximumBy with the signature
maximumBy :: (a -> a -> Ordering) -> [a] -> a
and Data.Function has on with the signature
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
Applied with the compare function (compare :: Ord a => a -> a -> Ordering), we can see how this is exactly what you're looking for.
import Data.List (maximumBy)
import Data.Function (on)
{- for clarity:
compare :: Ord a => b -> b -> Ordering
(compare `on`) :: Ord b => (a -> b) -> a -> a -> Ordering
compare `on` sum :: (Num a, Ord a) => [a] -> [a] -> Ordering
-- well actually [a] is t a for a foldable t, but same diff -}
result = maximumBy (compare `on` sum) [[1,2],[3,6],[10,34,5]]
to implement this yourself, you could write a fold that compares each value according to its sum, recursing until the sum of x is greater than anything that comes before after it.
myMaximumBySum [] = [] -- degenerate case
myMaximumBySum [x] = x -- tautological case
myMaximumBySum (x:xs)
| sum x > sum (myMaximumBySum xs) = x
| otherwise = myMaximumBySum xs
-- or more naturally:
myMaximumBySum = foldr f []
where f x acc = if sum x > sum acc then x else acc

Haskell search an element on a List

I want a function that changes (1 to 0) on a list of lists, when number of 1's in that line/column isn't even. I have done these functions:
1) Sees if the lines in a list are even or not:
parityLine :: [[Int]] -> [Bool]
parityLine [] =[]
parityLine (x:xs)
|sum(x) `mod` 2 == 0 = True:(parityLine(xs))
|otherwise = False:(parityLine(xs))
2) Sum the corresponding elements on a list of lists:
sumPositions :: [[Int]] -> [Int]
sumPositions [] = []
sumPositions (x:xs) = foldl (zipWith (+)) (repeat 0) (x:xs)
3) Sees if the columns in a list are even or not:
parityColumn :: [Int] -> [Bool]
parityColumn [] = []
parityColumn (x:xs)
|head(x:xs) `mod` 2 == 0 = True:parityColumn(xs)
|otherwise = False:parityColumn(xs)
4) Does the operation or with two boolean lists:
bol :: [Bool] -> [Bool] -> [[Bool]]
bol [] _ = []
bol (x:xs) (y:ys)= (map (||x) (y:ys)):(bol xs (y:ys))
5) Correct List:
correct :: [[Int]] -> [[Bool]]
correct [] = []
correct (x:xs)=(bol(parityLine (x:xs))(parityColumn(sumPositions(x:xs))))
So what I want is to alter the function correct to [[Int]]->[[Int]] that does this:
My Int list(x:xs) With my correct function applied
[[0,0,1,1], [[True,True,True,True],
[1,0,1,1], [True,True,False,True],
[0,1,0,1], [True,True,True,True]
[1,1,1,1]] [True,True,True,True]]
Now I can see that in the second line third column, False, so I have to correct that number 1 to have a number of 1's even. If there is more than one False in that list, I only want to correct one of these 1's.
As a result, I want that function correct returns:
[[0,0,1,1],
[1,0,0,1],
[0,1,0,1],
[1,1,1,1]]
Thanks.
I'll give an answer that starts where you are rather than from scratch, so we're doing it more your way than mine.
First let's do it for a single element:
leaveIf :: Bool -> Int -> Int
leaveIf yes 0 = if yes then 0 else 1
leaveIf yes 1 = if yes then 1 else 0
(You could use guards for that, but my phone doesn't have the vertical bar character!)
Next we can do it for a list of lists:
edit :: [[Bool]] -> [[Int]] -> [[Int]]
edit boolss intss = zipWith (zipWith leaveIf) boolss intss
EDIT: You'd like to only change one, so we'll need a way of making subsequent Falses into Trues:
makeTrue :: [Bool] -> [Bool]
makeTrue xs = map (const True) xs
I've used the function const :: a -> b -> a. For example, const 5 'c' is just 5. I could shorten that definition to makeTrue = map (const True). Once you get used to thinking that way, you'll find the shorter version clearer.
oneFalse :: [[Bool]] -> [[Bool]]
oneFalse [] = []
oneFalse (xs:xss) = let (trues,falses) = break (==False) xs in
case falses of
[] -> trues:oneFalse xss
(False:others) -> (trues ++ False : makeTrue others) : map makeTrue xss
(==False) could be written more simply as not, but less clearly perhaps.
so for example
> oneFalse [[True,True,True,True],[True,False,True,False],[True,False,False,True]]
[[True,True,True,True],[True,False,True,True],[True,True,True,True]]
So now we can have
editOne :: [[Bool]] -> [[Int]] -> [[Int]]
editOne boolss intss = zipWith (zipWith leaveIf) (oneFalse boolss) intss
AndrewC already gave an solution which changed all 1s corresponding to Falses. If we only want to correct the first one, we have to find a replacement for zipWith:
leaveIf ok x = if ok then x else 1 -x
-- Varianto of zipWith, which changes at most one element of the list
modFirst :: Eq b => (a -> b -> b) -> [a] -> [b] -> [b]
modFirst _ [] _ = []
modFirst _ _ [] = []
modFirst f (x:xs) (y:ys) = z : if y == z then modFirst f xs ys else ys
where z = f x y
edit :: [[Bool]] -> [[Int]] -> [[Int]]
edit boolss intss = modFirst (modFirst leaveIf) boolss intss
correct' :: [[Int]] -> [[Int]]
correct' xss = edit (correct' xss) xss
The result is the not necessarily a list of lists where all lines/rows contain an even number of 1's:
correct' [[0,1,0],[1,1,1],[0,1,0]] = [[1,1,0],[1,1,1],[0,1,0]
You need to iterate it a few times, until all errors are fixed (i.e., compute a fixpoint).
I'd like to add that your original program can be simplified quite a bit (without changing your algorithm):
parityLine :: [[Int]] -> [Bool]
parityLine = map (even . sum)
parityColumn :: [Int] -> [Bool]
parityColumn = map even
sumPositions :: [[Int]] -> [Int]
sumPositions = foldl (zipWith (+)) (repeat 0)
bol :: [Bool] -> [Bool] -> [[Bool]]
bol xs ys = map (\x -> map (||x) ys) xs
correct :: [[Int]] -> [[Bool]]
correct xs = bol (parityLine xs) (parityColumn $ sumPositions xs)

Resources