Finding The Index of Element in an Array - Haskell - haskell

Which function can I use to find its index of an element in an Array?
For example, I want to find the index of 'x' in an Array (Data.Array)
lowerCase = listArray ((0,0),(1,12)) ['a'..]

fst <$> find ((== 'a') . snd) $ assocs lowerCase

To get all the indices a certain element appears in your Data.Array the following list comprehension can be used:
results = [fst x | x <- (assocs lowerCase), snd x == 'a']
assocs has the following prototype:
assocs :: Ix i => Array i e -> [(i, e)]
It basically flattens a Data.Array in a List containing (i, e) pairs.
For:
a = listArray ((0,0),(2,2)) ['a'..]
assocs a will output
[((0,0),'a'),((0,1),'b'),((0,2),'c'),((1,0),'d'),((1,1),'e'),((1,2),'f'),((2,0),'g'),((2,1),'h'),((2,2),'i')]
Now, in our list comprehension, we have x <- (assocs a), so x is generated by the list assocs a.
The list outputed by the list comprehension will contain only fst x where
snd x == theElementWeAreLookingFor
Every x generated by assocs a is checked and if the condition snd x == 'a' is met then fst a (the index) will be inserted in the output list.
Once the list is generated, it can be checked whether there are none, one or more outputs.
getElementIndex :: Array (Int, Int) Char -> Char -> Maybe (Int, Int)
getElementIndex a e
| null results = Nothing
| othwerwise = Just $ head results
where results = [fst x | x <- (assocs a), snd x == e]
A imperative pseduocode could look like:
results = []
for_each x in a.toList():
if x.second == 'a':
results.append(x.first)

Related

Why does my backtracking always return an empty list?

I have a function, test p xs = [(x,y) | (x:ys) <- tails xs, y <- ys, p x y], which returns a list of all tuples which fulfil a predicate such as (\x -> \y -> x*y < 45), for a specified list such as [2..11]. I want to create a maximum maximal independent set: each number in the list is included once, no more and no less. A sample solution for the above predicate and list would be [(2,11),(3,10),(4,9),(5,8),(6,7)].
My current backtracking script is as follows:
notInList pair list
| list == [] = True
| (fst pair) `elem` (tupleToList list) || (snd pair) `elem` (tupleToList list) = False
| otherwise = True
gen pairs final len = do
pair <- pairs
guard $ notInList pair final
if (length final) == len
then return [pair]
else do
next <- gen (delete pair pairs) (pair : final) len
return $ pair : next
tupleToList :: [(a,a)] -> [a]
tupleToList ((a,b):xs) = a : b : tupleToList xs
tupleToList _ = []
I run gen (test (\x -> \y -> x*y < 45) [2..11]) [] 5, which as far as I can tell should backtrack to the right solution eventually, but the script always returns an empty list. I've tried it on other lists and predicates with a valid solution too, and I'm not sure what's going wrong and how I could fix this script to do what I need it to do. I'm not sure whether returning the empty list suggests that it found no solutions, or if it just breaks somewhere in the middle.
This part is suspicious:
guard $ notInList pair final
if (length final) == len
Suppose final is a maximal independent set, so length final == len, where len is the length of the result that you know in advance. Then the guard must be false, so you backtrack without reaching that if.
Put the test of whether you got the final result at the beginning of the function:
gen :: Eq a => [(a, a)] -> [(a, a)] -> Int -> [[(a, a)]]
gen pairs final len | length final == len = return final
gen pairs final len | otherwise = do
-- Take a "pair" out and shadow "pairs" with the remainder.
-- Use "tails" to avoid creating duplicate sets.
-- For example, if you have a list [p1, p2, ...] you want
-- to try to pick p1 then p2, but after backtracking, it's no use trying p2 then p1.
pair : pairs <- tails pairs
guard $ notInList pair final
gen pairs (pair : final) len

Haskell don't really know what to name this

I'm trying to make it so that on a tuple input (n,m) and a list of tuples xs , if the first item in the tuple in xs is in (n,m) then keep it that way in the new list otherwise add the a tuple consisting of some value k from n to m as a first element and as second element it should be 0.My question is:how can i say "repeat 0" using guards ? Since clearly my code won't run since my code says "repeat = 0"
expand :: (Int,Int) -> Profile ->Profile
expand (n,m) [] = zip [n..m] (repeat 0)
expand (n,m) (x:xs) = zip [n..m] (repeat (|(fst (x) `elem` [n..m]) == False = 0
|otherwise = snd (x))
You can use a helper function here that converts a number in the [ n .. m ] range to a 2-tuple. Here we thus try to find an element in the list xs that matches with the first item of that tuple, if we do not find such element, we use 0:
import Data.List(find)
expand :: (Int,Int) -> Profile -> Profile
expand (n,m) xs = map go [n .. m]
where go i | Just l <- find (\(f, _) -> f == i) xs = l
| otherwise = (i, 0)
For a list, find was implemented as [src]:
find :: (a -> Bool) -> [a] -> Maybe a
find p = listToMaybe . filter p
filter thus will make a list that contains the elements that satisfy the predicate p, and listToMaybe :: [a] -> Maybe a will convert an empty list [] to Nothing, and for a non-empty list (x:_) it will wrap the first element x in a Just data constructor. Due to Haskell's laziness, it will thus look for the first element that satisfies the predicate.
this thus gives us:
Prelude Data.List> expand (2,7) [(4, 2.3), (6, 3)]
[(2,0.0),(3,0.0),(4,2.3),(5,0.0),(6,3.0),(7,0.0)]

Count a occurrence of a specific word in a sentence haskell

I'm new in Haskell and I'm tring to write a simple function that counts the number of occurences of a substring in a string.
For example : "There is an apple" and I want to count how many times "is" in the sentence, in this case the result should be 1.
This is what I've tried:
countOf :: String -> Int
countOf x = length [n | n <- words x, filter "is" x]
According what I've studied it should work, but it doesn't. I really don't know how to solve the problem, and also don't know what the error message I get means:
input:1:41:
Couldn't match expected type `Bool' with actual type `[a0]'
In the return type of a call of `filter'
In the expression: filter "a" x
In a stmt of a list comprehension: filter "a" x
The function filter has the type
filter :: (a -> Bool) -> [a] -> [a]
This means that its first argument is another function, which takes an element and returns a Bool, and it applies this function to each element of the second argument. You're giving a String as the first argument instead of a function. Maybe you want something more like
countOf x = length [n | n <- words x, filter (\w -> w == "is") x]
But this won't work either! This is because any extra expression in a list comprehension has to be a Bool, not a list. filter returns a list of elements, not a Bool, and this is actually the source of your compiler error, it expects a Bool but it sees a list of type [a0] (it hasn't even gotten far enough to realize it should be [String]).
Instead, you could do
countOf x = length [n | n <- words x, n == "is"]
And this would be equivalent to
countOf x = length (filter (\w -> w == "is") (words x))
Or with $:
countOf x = length $ filter (\w -> w == "is") $ words x
Haskell will actually let us simplify this even further to
countOf x = length $ filter (== "is") $ words x
Which uses what is known as an operator section. You can then make it completely point free as
countOf = length . filter (== "is") . words
I would do like this:
countOf :: String -> Int
countOf x = length [n | n <- words x, compare "is" n == EQ]
Demo in ghci:
ghci> countOf "There is an apple"
1
You can put the comparison straight in the comprehension:
countOf x = length [n | n <- words x, n == "is"]
Actually, you try to count the number of occurences of a word in a string. In case you look for a substring:
import Data.List (inits, tails)
countOf = length . filter (=="is") . conSubsequences
where
conSubsequences = concatMap inits . tails
One could also try a foldr:
countOf :: String -> Int
countOf x = foldr count 0 (words x)
where
count x acc = if x == "is" then acc + 1 else acc

Two way searching a list of tuples

tuplesList = [('a','m'), ('b', 'n'), ('c', 'o'), etc]
How do I search this list for a value by first looking at first elements and returning the second if found, but if not found then look at the second elements and return the first element if found. e.g. searching for 'a' would return 'm' and searching for 'n' returns 'b'?
I tried this:
lookup :: Char -> [(Char,Char)] -> Char
lookup x zs = (head [b | (a,b) <- zs, (a==x)])
lookup x zs = (head [a | (a,b) <- zs, (b==x)])
but I don't know how to say if the the 2nd line doesn't find a match then do the 3rd line.
Any help is appreciated.
Haskell already has its own lookup function which you should probably make use of:
lookup' :: Char -> [(Char,Char)] -> Char
lookup' x zs = case (search1, search2) of
(Just y, _) -> y
(Nothing, Just y) -> y
(Nothing, Nothing) -> error "What am I supposed to do here I DON'T KNOW"
where search1 = lookup x zs
search2 = lookup x [(b,a) | (a,b) <- zs]
A nice way to expand your partial solution is to just concatenate the two lists of candidates together, as in:
lookup x zs = head ([ b | (a,b) <- zs, a == x ] ++ [ a | (a,b) <- zs, b == x ])
Do you see why this works?
It's not maximally efficient, because if there's no match on the first component of the tuples it will go through zs twice - if zs is very large this holds on to zs longer than necessary.
In order to improve that I would do something like this (but only if it's very important!):
lookup x zs = goNoSecondBestYet zs where
goNoSecondBestYet [] = error "Nothing found"
goNoSecondBestYet ((a,b):abs)
| a == x = b -- we're done!
| b == x = goSecondBestFound b abs -- keep track of the newly found second best candidate
| otherwise = goNoSecondBestYet abs -- just go on
goSecondBestFound y [] = y
goSecondBestFound y ((a,b):abs)
| a == x = b -- we're done, never mind the second best
| otherwise = goSecondBestFound y abs -- keep going, we already have a second best
This is pretty complex already (try to generalise this to use 4-tuples to see what I mean!) and I would normally use Maybe for this; but it does go through the list only once.
You should consider that a lookup may fail. The natural thing to do here is to return a list of results:
lookup :: Eq a => a -> (a,a) -> [a]
lookup item xs = [ if a==c then b else a | (a,b) <- xs, a == c || b == c ]

Haskell - Most frequent value

how can i get the most frequent value in a list example:
[1,3,4,5,6,6] -> output 6
[1,3,1,5] -> output 1
Im trying to get it by my own functions but i cant achieve it can you guys help me?
my code:
del x [] = []
del x (y:ys) = if x /= y
then y:del x y
else del x ys
obj x []= []
obj x (y:ys) = if x== y then y:obj x y else(obj x ys)
tam [] = 0
tam (x:y) = 1+tam y
fun (n1:[]) (n:[]) [] =n1
fun (n1:[]) (n:[]) (x:s) =if (tam(obj x (x:s)))>n then fun (x:[]) ((tam(obj x (x:s))):[]) (del x (x:s)) else(fun (n1:[]) (n:[]) (del x (x:s)))
rep (x:s) = fun (x:[]) ((tam(obj x (x:s))):[]) (del x (x:s))
Expanding on Satvik's last suggestion, you can use (&&&) :: (b -> c) -> (b -> c') -> (b -> (c, c')) from Control.Arrow (Note that I substituted a = (->) in that type signature for simplicity) to cleanly perform a decorate-sort-undecorate transform.
mostCommon list = fst . maximumBy (compare `on` snd) $ elemCount
where elemCount = map (head &&& length) . group . sort $ list
The head &&& length function has type [b] -> (b, Int). It converts a list into a tuple of its first element and its length, so when it is combined with group . sort you get a list of each distinct value in the list along with the number of times it occurred.
Also, you should think about what happens when you call mostCommon []. Clearly there is no sensible value, since there is no element at all. As it stands, all the solutions proposed (including mine) just fail on an empty list, which is not good Haskell. The normal thing to do would be to return a Maybe a, where Nothing indicates an error (in this case, an empty list) and Just a represents a "real" return value. e.g.
mostCommon :: Ord a => [a] -> Maybe a
mostCommon [] = Nothing
mostCommon list = Just ... -- your implementation here
This is much nicer, as partial functions (functions that are undefined for some input values) are horrible from a code-safety point of view. You can manipulate Maybe values using pattern matching (matching on Nothing and Just x) and the functions in Data.Maybe (preferable fromMaybe and maybe rather than fromJust).
In case you would like to get some ideas from code that does what you wish to achieve, here is an example:
import Data.List (nub, maximumBy)
import Data.Function (on)
mostCommonElem list = fst $ maximumBy (compare `on` snd) elemCounts where
elemCounts = nub [(element, count) | element <- list, let count = length (filter (==element) list)]
Here are few suggestions
del can be implemented using filter rather than writing your own recursion. In your definition there was a mistake, you needed to give ys and not y while deleting.
del x = filter (/=x)
obj is similar to del with different filter function. Similarly here in your definition you need to give ys and not y in obj.
obj x = filter (==x)
tam is just length function
-- tam = length
You don't need to keep a list for n1 and n. I have also made your code more readable, although I have not made any changes to your algorithm.
fun n1 n [] =n1
fun n1 n xs#(x:s) | length (obj x xs) > n = fun x (length $ obj x xs) (del x xs)
| otherwise = fun n1 n $ del x xs
rep xs#(x:s) = fun x (length $ obj x xs) (del x xs)
Another way, not very optimal but much more readable is
import Data.List
import Data.Ord
rep :: Ord a => [a] -> a
rep = head . head . sortBy (flip $ comparing length) . group . sort
I will try to explain in short what this code is doing. You need to find the most frequent element of the list so the first idea that should come to mind is to find frequency of all the elements. Now group is a function which combines adjacent similar elements.
> group [1,2,2,3,3,3,1,2,4]
[[1],[2,2],[3,3,3],[1],[2],[4]]
So I have used sort to bring elements which are same adjacent to each other
> sort [1,2,2,3,3,3,1,2,4]
[1,1,2,2,2,3,3,3,4]
> group . sort $ [1,2,2,3,3,3,1,2,4]
[[1,1],[2,2,2],[3,3,3],[4]]
Finding element with the maximum frequency just reduces to finding the sublist with largest number of elements. Here comes the function sortBy with which you can sort based on given comparing function. So basically I have sorted on length of the sublists (The flip is just to make the sorting descending rather than ascending).
> sortBy (flip $ comparing length) . group . sort $ [1,2,2,3,3,3,1,2,4]
[[2,2,2],[3,3,3],[1,1],[4]]
Now you can just take head two times to get the element with the largest frequency.
Let's assume you already have argmax function. You can write
your own or even better, you can reuse list-extras package. I strongly suggest you
to take a look at the package anyway.
Then, it's quite easy:
import Data.List.Extras.Argmax ( argmax )
-- >> mostFrequent [3,1,2,3,2,3]
-- 3
mostFrequent xs = argmax f xs
where f x = length $ filter (==x) xs

Resources