elemIndices in Haskell - haskell

I wrote the code to get the element index
elemIndex :: [String] -> [String] -> [Int]
elemIndex [] [] = []
elemIndex x y = elemIndex True [(elem a y) | a <- x ]
is there any alternative way/similer of performing the above logic?
and also i've seen that some use
index [] _ = []
to return null lists
could you pls explain the use of underscore?
//edit 1
it is suposed to return the index of the values in the list.
eg: elemIndex ["asde","zxc","qwe"] ["qwe","zxc"]
returns [1,2] as the answer
thanks

elemIndex takes two arguments (two lists). Right now you recursively call it with an additional argument of type bool (namely True). That will not work. What you probably want to do, is create a helper function, as I showed you an hour ago.
The _, as used as a formal argument, matches any input. It does not have a name, and as such, you cannot use that which is matched.
Aside from that, you probably don't want to use booleans, but integers (to keep track of a counter). The elem function only tells you whether some value is part of a list, not where it is. So, it is of little use to you. Since this appears to be homework I will not provide a solution to your problem, but perhaps you should split your code in two:
indices :: (Eq t) => [t] -> [t] -> [Integer]
getIndex :: (Eq t) => [t] -> t -> Integer
(getIndex may use a helper function getIndex' :: (Eq t) => [t] -> t -> Integer -> Integer.)
Edit: One possible solution (which uses a hack, it's nicer to use the Maybe monad):
indices :: (Eq t) => [t] -> [t] -> [Integer]
indices xs ys = filter (>= 0) $ map (getIndex xs) ys
getIndex :: (Eq t) => [t] -> t -> Integer
getIndex xs y = getIndex' xs y 0
where
getIndex' :: (Eq t) => [t] -> t -> Integer -> Integer
getIndex' [] _ _ = -1
getIndex' (x:xs) y i | x == y = i
| otherwise = getIndex' xs y (i + 1)
A version with the Maybe monad:
import Data.Maybe
indices :: (Eq t) => [t] -> [t] -> [Integer]
indices xs ys = mapMaybe (getIndex xs) ys
getIndex :: (Eq t) => [t] -> t -> Maybe Integer
getIndex xs y = getIndex' xs y 0
where
getIndex' :: (Eq t) => [t] -> t -> Integer -> Maybe Integer
getIndex' [] _ _ = Nothing
getIndex' (x:xs) y i | x == y = Just i
| otherwise = getIndex' xs y (i + 1)
And a version that leaves all heavy lifting to the standard library:
import Data.List
import Data.Maybe
indices :: (Eq t) => [t] -> [t] -> [Int]
indices xs ys = mapMaybe (`elemIndex` xs) ys

index [] _ = []
is the same as
index [] x = []
except you cannot use the _ on the right hand side of the equals sign.
I don't understand what you want elemIndex to do.

I'd implement your function this way:
elemIndices acc n [] _ = acc
elemIndices acc n _ [] = acc
elemIndices acc n (x:x') (y:y') = if x == y then
elemIndices (n:acc) (n+1) x' y'
else
elemIndices acc (n+1) x' (y:y')
elemIndex x y = reverse $ elemIndices [] 1 x y
When the elements in your source list are in the same order as the elements you look for, this is much more efficient (no use of elem - tail recursion). Ex:
elemIndex [3..7] [4, 6] -- Yields [2, 4]

Related

create a function ved that will only remove the last occurrence of the largest item in the list using recursion

You must use recursion to define rmax2 and you must do so from “scratch”. That is, other than the cons operator, head, tail, and comparisons, you should not use any functions from the Haskell library.
I created a function that removes all instances of the largest item, using list comprehension. How do I remove the last instance of the largest number using recursion?
ved :: Ord a => [a] -> [a]
ved [] =[]
ved as = [ a | a <- as, m /= a ]
where m= maximum as
An easy way to split the problem into two easier subproblems consists in:
get the position index of the rightmost maximum value
write a general purpose function del that eliminates the element of a list at a given position. This does not require an Ord constraint.
If we were permitted to use regular library functions, ved could be written like this:
ved0 :: Ord a => [a] -> [a]
ved0 [] = []
ved0 (x:xs) =
let
(maxVal,maxPos) = maximum (zip (x:xs) [0..])
del k ys = let (ys0,ys1) = splitAt k ys in (ys0 ++ tail ys1)
in
del maxPos (x:xs)
where the pairs produced by zip are lexicographically ordered, thus ensuring the rightmost maximum gets picked.
We need to replace the library functions by manual recursion.
Regarding step 1, that is finding the position of the rightmost maximum, as is commonly done, we can use a recursive stepping function and a wrapper above it.
The recursive step function takes as arguments the whole context of the computation, that is:
current candidate for maximum value, mxv
current rightmost position of maximum value, mxp
current depth into the original list, d
rest of original list, xs
and it returns a pair: (currentMaxValue, currentMaxPos)
-- recursive stepping function:
findMax :: Ord a => a -> Int -> Int -> [a] -> (a, Int)
findMax mxv mxp d [] = (mxv,mxp)
findMax mxv mxp d (x:xs) = if (x >= mxv) then (findMax x d (d+1) xs)
else (findMax mxv mxp (d+1) xs)
-- top wrapper:
lastMaxPos :: Ord a => [a] -> Int
lastMaxPos [] = (-1)
lastMaxPos (x:xs) = snd (findMax x 0 1 xs)
Step 2, eliminating the list element at position k, can be handled in very similar fashion:
-- recursive stepping function:
del1 :: Int -> Int -> [a] -> [a]
del1 k d [] = []
del1 k d (x:xs) = if (d==k) then xs else x : del1 k (d+1) xs
-- top wrapper:
del :: Int -> [a] -> [a]
del k xs = del1 k 0 xs
Putting it all together:
We are now able to write our final recursion-based version of ved. For simplicity, we inline the content of wrapper functions instead of calling them.
-- ensure we're only using authorized functionality:
{-# LANGUAGE NoImplicitPrelude #-}
import Prelude (Ord, Eq, (==), (>=), (+), ($), head, tail,
IO, putStrLn, show, (++)) -- for testing only
ved :: Ord a => [a] -> [a]
ved [] = []
ved (x:xs) =
let
findMax mxv mxp d [] = (mxv,mxp)
findMax mxv mxp d (y:ys) = if (y >= mxv) then (findMax y d (d+1) ys)
else (findMax mxv mxp (d+1) ys)
(maxVal,maxPos) = findMax x 0 1 xs
del1 k d (y:ys) = if (d==k) then ys else y : del1 k (d+1) ys
del1 k d [] = []
in
del1 maxPos 0 (x:xs)
main :: IO ()
main = do
let xs = [1,2,3,7,3,2,1,7,3,5,7,5,4,3]
res = ved xs
putStrLn $ "input=" ++ (show xs) ++ "\n" ++ " res=" ++ (show res)
If you are strictly required to use recursion, you can use 2 helper functions: One to reverse the list and the second to remove the first largest while reversing the reversed list.
This result in a list where the last occurrence of the largest element is removed.
We also use a boolean flag to make sure we don't remove more than one element.
This is ugly code and I really don't like it. A way to make things cleaner would be to move the reversal of the list to a helper function outside of the current function so that there is only one helper function to the main function. Another way is to use the built-in reverse function and use recursion only for the removal.
removeLastLargest :: Ord a => [a] -> [a]
removeLastLargest xs = go (maximum xs) [] xs where
go n xs [] = go' n True [] xs
go n xs (y:ys) = go n (y:xs) ys
go' n f xs [] = xs
go' n f xs (y:ys)
| f && y == n = go' n False xs ys
| otherwise = go' n f (y:xs) ys
Borrowing the implementation of dropWhileEnd from Hackage, we can implement a helper function splitWhileEnd:
splitWhileEnd :: (a -> Bool) -> [a] -> ([a], [a])
splitWhileEnd p = foldr (\x (xs, ys) -> if p x && null xs then ([], x:ys) else (x:xs, ys)) ([],[])
splitWhileEnd splits a list according to a predictor from the end. For example:
ghci> xs = [1,2,3,4,3,2,4,3,2]
ghci> splitWhileEnd (< maximum xs) xs
([1,2,3,4,3,2,4],[3,2])
With this helper function, you can write ven as:
ven :: Ord a => [a] -> [a]
ven xs =
let (x, y) = splitWhileEnd (< maximum xs) xs
in init x ++ y
ghci> ven xs
[1,2,3,4,3,2,3,2]
For your case, you can refactor splitWhileEnd as:
fun p = \x (xs, ys) -> if p x && null xs then ([], x:ys) else (x:xs, ys)
splitWhileEnd' p [] = ([], [])
splitWhileEnd' p (x : xs) = fun p x (splitWhileEnd' p xs)
ven' xs = let (x, y) = splitWhileEnd' (< maximum xs) xs in init x ++ y
If init and ++ are not allowed, you can implement them manually. It's easy!
BTW, I guess this may be your homework for Haskell course. I think it's ridiculous if your teacher gives the limitations. Who is programming from scratch nowadays?
Anyway, you can always work around this kind of limitations by reimplementing the built-in function manually. Good luck!

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.

How to pattern match the end of a list?

Say I wanted to remove all zeros at the end of a list:
removeEndingZeros :: (Num a, Eq a) => [a] -> [a]
removeEndingZeros (xs ++ [0]) = removeEndingZeros xs
removeEndingZeros xs = xs
This does not work because of the (++) operator in the argument. How can I determine the end of a list through pattern-matching?
There is a function in Data.List to do this:
dropWhileEnd :: (a -> Bool) -> [a] -> [a]
dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []
So you can drop the trailing zeros with
dropWhileEnd (== 0)
Another, very similar, function can be implemented like this:
dropWhileEnd2 :: (a -> Bool) -> [a] -> [a]
dropWhileEnd2 p = foldr (\x xs -> if null xs && p x then [] else x : xs) []
dropWhileEnd2 p has exactly the same semantics as reverse . dropWhile p . reverse, but can reasonably be expected to be faster by a constant factor. dropWhileEnd has different, non-comparable strictness properties than the others (it's stricter in some ways and less strict in others).
Can you figure out circumstances under which each can be expected to be faster?

How to extract the same elements from two lists in Haskell?

here's my question:
How to extract the same elements from two equal length lists to another list?
For example: given two lists [2,4,6,3,2,1,3,5] and [7,3,3,2,8,8,9,1] the answer should be [1,2,3,3]. Note that the order is immaterial. I'm actually using the length of the return list.
I tried this:
sameElem as bs = length (nub (intersect as bs))
but the problem is nub removes all the duplications. The result of using my function to the former example is 3 the length of [1,3,2] instead of 4 the length of [1,3,3,2]. Is there a solution? Thank you.
Since the position seems to be irrelevant, you can simply sort the lists beforehand and then traverse both lists:
import Data.List (sort)
intersectSorted :: Ord a => [a] -> [a] -> [a]
intersectSorted (x:xs) (y:ys)
| x == y = x : intersectSorted xs ys
| x < y = intersectSorted xs (y:ys)
| x > y = intersectSorted (x:xs) ys
intersectSorted _ _ = []
intersect :: Ord a => [a] -> [a] -> [a]
intersect xs ys = intersectSorted (sort xs) (sort ys)
Note that it's also possible to achieve this with a Map:
import Data.Map.Strict (fromListWith, assocs, intersectionWith, Map)
type Counter a = Map a Int
toCounter :: Ord a => [a] -> Counter a
toCounter = fromListWith (+) . flip zip (repeat 1)
intersectCounter :: Ord a => Counter a -> Counter a -> Counter a
intersectCounter = intersectionWith min
toList :: Counter a -> [a]
toList = concatMap (\(k,c) -> replicate c k) . assocs
intersect :: Ord a => [a] -> [a] -> [a]
intersect xs ys = toList $ intersectCounter (toCounter xs) (toCounter ys)
You could write a function for this. There is probably a more elegant version of this involving lambda's or folds, but this does work for your example:
import Data.List
same (x:xs) ys = if x `elem` ys
then x:same xs (delete x ys)
else same xs ys
same [] _ = []
same _ [] = []
The delete x ys in the then-clause is important, without that delete command items from the first list that occur at least once will be counted every time they're encountered.
Note that the output is not sorted, since you were only interested in the length of the resulting list.
import Data.List (delete)
mutuals :: Eq a => [a] -> [a] -> [a]
mutuals [] _ = []
mutuals (x : xs) ys | x `elem` ys = x : mutuals xs (delete x ys)
| otherwise = mutuals xs ys
gives
mutuals [2,4,6,3,2,1,3,5] [7,3,3,2,8,8,9,1] == [2,3,1,3]

Using few functions in Haskell together

I made this code where I need to find elements in a list that appears only once
for example: for input [1,2,2,3,4,4], the output will be: [1,3]
unique :: =[a]->[a]
unique xs =[x|x<-xs, elemNum x xs ==1]
elemNum :: Int -> [Int]->[Int]
elemNum x (y:ys)
| x==y =1+ elemNum x ys
| otherwise =elemNum x ys
However I am getting an error :
Not in scope: `unique'
Is this the correct way to use 2 function in Haskell? (define them at the same file), What'a wrong with the code?
There are a few problems in your code:
type signature of unique is wrong, it should be
unique :: (Eq a) => [a] -> [a]
that type constraint (Eq a) comes from elemNum
type signature of elemNum also wrong, it should be
elemNum :: (Eq a) => a -> [a] -> Int
that type constraint comes from ==, and the type of its first parameter no need to be Int, but its return type should be Int because you want to find out how many x in xs.
Also, you forgot to deal with empty list in that definition.
Here is a fixed version of your code:
unique :: (Eq a) => [a] -> [a]
unique xs =[x| x<-xs, elemNum x xs == 1]
elemNum :: (Eq a) => a -> [a] -> Int
elemNum x [] = 0
elemNum x (y:ys)
| x==y = 1 + elemNum x ys
| otherwise = elemNum x ys
Here is another implementation:
onlyOnce [] = []
onlyOnce (x:xs)
| x `elem` xs = onlyOnce $ filter (/=x) xs
| otherwise = x : onlyOnce xs
If x occurs in xs, then the result of onlyOnce (x:xs) should be the same as the result of applying onlyOnce to the result of removing all occurrences of x from xs; otherwise, x occurs in (x:xs) only once, so x should be part of the final result.
You have an equals sign in the Type declaration for unique:
unique :: =[a]->[a]
should be
unique :: [a] -> [a]
In my opinion it is much easier to implement this function using functions from Data.List module:
import Data.List
unique :: (Ord a) => [a] -> [a]
unique = map (\(y,_) -> y) . filter (\(x,l) -> l == 1) . map (\l#(x:xs) -> (x,length l)) . group . sort

Resources