The function actually works but the list it returns, if the first element is equal to x, won't be in the correct order.
The function:
myelemIndices :: Eq a => a -> [a] -> [Int]
myelemIndices x [] = []
myelemIndices x l = if posic n l == x
then myReverse (n : myelemIndices x (init l))
else myelemIndices x (init l)
where n = length l - 1
Will return something like:
myelemIndices 1 [1,2,1,2,1]
[2,0,4]
Posic funtion is equal to :
posic :: Int -> [a] -> a
posic 0 (h:t) = h
posic x (a:b) = posic (x-1) b
And myReverse does exactly the same as reverse. I'm not looking for a different funtion that works, just a correction on mine. Thanks in advance!
You're reversing the list every time you find an element. The minimal change here would be to use myElemIndices x (init l) ++ [n] instead of myReverse (n : myelemIndices x (init l))
A first anti-pattern in your code is that you use length. length will usually run in O(n) (with n the number of elements in the list), but furthermore it is troublesome since the list can have infinite length. In that case length will never terminate. In functional programming it is sometimes seen as a sign that something is probably not right.
So the first question is: do we need length. What your code needs to do is return the indices. But say you for instance need to know on what pages in a phone book the name "John" is listed, then you do not need to know in advance how many pages the phone book has: you can simply take a look at the first page. In case it has a person with first name John, then you say that is on page 1, and regardless of that, you move further.
We can use the same approach here. The only thing we need is a parameter that keeps track of the page we are currently looking at. We can introduce this parameter by defining a new function that will do most of the work. So:
myElemIndices :: Eq a => a -> [a] -> [Int]
myElemIndices x l = go 0 l
where go = ...
So we defined a function go, and the first parameter will keep track of the page number. We will need to update that number in case we do recursion. But now of course we still need to define the go function.
The base case is easy: in case we reached the end of the list (phone book), we can say we will not find any occurences anymore. So we can write:
go _ [] = []
This thus means that, regardless of the page number (_), in case there are no pages anymore ([]), we return an empty list as match [].
In case we did not reach the end of the phone book, we can fetch the head h, and the tail t. We will have to check if the head h matches with the queried element x. In case it does, we return the page number, otherwise we don not. Regardless of that, we keep searching for more pages. So we can write:
go i (h:t) | x == h = i : <next-matches>
| otherwise = <next-matches>
the <next-matches> simply is a recursive call where we update the page number (i+1), and we continue with the tail of the list, so:
go i (h:t) | x == h = i : tl
| otherwise = tl
where tl = go (i+1) t
Now we can put that all together into:
myElemIndices :: Eq a => a -> [a] -> [Int]
myElemIndices x l = go 0 l
where go _ [] = []
go i (h:t) | x == h = i : tl
| otherwise = tl
where tl = go (i+1) t
We can still improve the code a bit. First of all, we do not have to write:
myElemIndices x l = go 0 l
Notice that both the head and the body end with l. We can omit this, and turn it into:
myElemIndices x = go 0
Furthermore we do not need the result to be Ints as well. As long as these are Nums, we are fine. So we can generalize this to:
myElemIndices :: (Eq a, Num n) => a -> [a] -> [n]
myElemIndices x l = go 0 l
where go _ [] = []
go i (h:t) | x == h = i : tl
| otherwise = tl
where tl = go (i+1) t
Related
Consider a function, which takes a string and returns a list of all possible cases in which three subsequent 'X's can be removed from the list.
Example:
"ABXXXDGTJXXXDGXF" should become
["ABDGTJXXXDGXF", "ABXXXDGTJDGXF"]
(The order does not matter)
here is a naive implementation:
f :: String -> [String]
f xs = go [] xs [] where
go left (a:b:c:right) acc =
go (left ++ [a]) (b:c:right) y where -- (1)
y = if a == 'X' && b == 'X' && c == 'X'
then (left ++ right) : acc
else acc
go _ _ acc = acc
I think the main problem here is the line marked with (1). I'm constructing the left side of the list by appending to it, which is generally expensive.
Usually something like this can be solved by this pattern:
f [] = []
f (x:xs) = x : f xs
Or more explicitly:
f [] = []
f (x:right) = x : left where
left = f right
Now I'd have the lists right and left in each recursion. However, I need to accumulate them and I could not figure out how to do so here. Or am I on the wrong path?
A solution
Inspired by Gurkenglas' propose, here is a bit more generalized version of it:
import Data.Bool
removeOn :: (String -> Bool) -> Int -> String -> [String]
removeOn onF n xs = go xs where
go xs | length xs >= n =
bool id (right:) (onF mid) $
map (head mid:) $
go (tail xs)
where
(mid, right) = splitAt n xs
go _ = []
removeOn (and . map (=='X')) 3 "ABXXXDGTJXXXDGXF"
--> ["ABDGTJXXXDGXF","ABXXXDGTJDGXF"]
The main idea seems to be the following:
Traverse the list starting from its end. Make use of a 'look-ahead' mechanism which can examine the next n elements of the list (thus it must be checked, if the current list contains that many elements). By this recursive traversal an accumulating list of results is being enhanced in the cases the following elements pass a truth test. In any way those results must be added the current first element of the list because they stem from shorter lists. This can be done blindly, since adding characters to a result string won't change their property of being a match.
f :: String -> [String]
f (a:b:c:right)
= (if a == 'X' && b == 'X' && c == 'X' then (right:) else id)
$ map (a:) $ f (b:c:right)
f _ = []
I'm new to Haskell. I need a function to swap two elements in a list when I know only the values.
For example:
swap 5 6 [1,5,7,6,4,3,2] -> [1,6,7,5,4,3,2]
5 and 6 are the values not the index, and the index of the values can be any.
It might help if you think about this task as reconstructing the list with the values swapped. The type signature is going to be like this. You're taking in two numbers to be swapped, and a list.
swap :: Int -> Int -> [Int] -> [Int]
You've got a couple of cases now. If the list is empty, that's easy. This is your base case.
swap _ _ [] = []
If the list isn't empty, then you've got two choices. Either the head of the list is a number you are interested in, or it's not. In the case where it matches, swap the value, otherwise just rebuild the list.
swap n m (x:xs)
| n == x = m : (swap n m xs)
| m == x = n : (swap n m xs)
| otherwise = x : (swap n m xs)
Once you've got this situation, you can see that you're doing an operation on every element. Now you can convert it over to the map solution (which is far more idiomatic!).
swap a b = map (\x -> if x == a then b else if x == b then a else x)
EDIT: Ah, I am afraid I only noticed that this question was answered in a comment above in the exact same way after I posted my answer. Apologies.
The function I'm trying to write should remove the element at the given index from the given list of any type.
Here is what I have already done:
delAtIdx :: [x] -> Int -> [x]
delAtIdx x y = let g = take y x
in let h = reverse x
in let b = take (((length x) - y) - 1) h
in let j = g ++ (reverse b)
in j
Is this correct? Could anyone suggest another approach?
It's much simpler to define it in terms of splitAt, which splits a list before a given index. Then, you just need to remove the first element from the second part and glue them back together.
reverse and concatenation are things to avoid if you can in haskell. It looks like it would work to me, but I am not entirely sure about that.
However, to answer the "real" question: Yes there is another (easier) way. Basically, you should look in the same direction as you always do when working in haskell: recursion. See if you can make a recursive version of this function.
Super easy(I think):
removeIndex [] 0 = error "Cannot remove from empty array"
removeIndex xs n = fst notGlued ++ snd notGlued
where notGlued = (take (n-1) xs, drop n xs)
I'm a total Haskell noob, so if this is wrong, please explain why.
I figured this out by reading the definition of splitAt. According to Hoogle, "It is equivalent to (take n xs, drop n xs)". This made me think that if we just didn't take one extra number, then it would be basically removed if we rejoined it.
Here is the article I referenced Hoogle link
Here's a test of it running:
*Main> removeIndex [0..10] 4
[0,1,2,4,5,6,7,8,9,10]
deleteAt :: Int -> [a] -> [a]
deleteAt 0 (x:xs) = xs
deleteAt n (x:xs) | n >= 0 = x : (deleteAt (n-1) xs)
deleteAt _ _ = error "index out of range"
Here is my solution:
removeAt xs n | null xs = []
removeAt (x:xs) n | n == 0 = removeAt xs (n-1)
| otherwise = x : removeAt xs (n-1)
remove_temp num l i | elem num (take i l) == True = i
| otherwise = remove_temp num l (i+1)
remove num l = (take (index-1) l) ++ (drop index l)
where index = remove_temp num l 1
Call 'remove' function with a number and a list as parameters. And you'll get a list without that number as output.
In the above code, remove_temp function returns the index at which the number is present in the list. Then remove function takes out the list before the number and after the number using inbuilt 'take' and 'drop' function of the prelude. And finally, concatenation of these two lists is done which gives a list without the input number.
im searching for a solution for my Haskell class.
I have a list of numbers and i need to return SUM for every part of list. Parts are divided by 0. I need to use FOLDL function.
Example:
initial list: [1,2,3,0,3,4,0,5,2,1]
sublist [[1,2,3],[3,4],[5,2,1]]
result [6,7,7]
I have a function for finding 0 in initial list:
findPos list = [index+1 | (index, e) <- zip [0..] list, e == 0]
(returns [4,6] for initial list from example)
and function for making SUM with FOLDL:
sumList list = foldl (+) 0 list
But I completely failed to put it together :/
---- MY SOLUTION
In the end I found something completely different that you guys suggested.
Took me whole day to make it :/
groups :: [Int] -> [Int]
groups list = [sum x | x <- makelist list]
makelist :: [Int] -> [[Int]]
makelist xs = reverse (foldl (\acc x -> zero x acc) [[]] xs)
zero :: Int -> [[Int]] -> [[Int]]
zero x acc | x == 0 = addnewtolist acc
| otherwise = addtolist x acc
addtolist :: Int -> [[Int]] -> [[Int]]
addtolist i listlist = (i : (head listlist)) : (drop 1 listlist)
addnewtolist :: [[Int]] -> [[Int]]
addnewtolist listlist = [] : listlist
I'm going to give you some hints, rather than a complete solution, since this sounds like it may be a homework assignment.
I like the breakdown of steps you've suggested. For the first step (going from a list of numbers with zero markers to a list of lists), I suggest doing an explicit recursion; try this for a template:
splits [] = {- ... -}
splits (0:xs) = {- ... -}
splits (x:xs) = {- ... -}
You can also abuse groupBy if you're careful.
For the second step, it looks like you're almost there; the last step you need is to take a look at the map :: (a -> b) -> ([a] -> [b]) function, which takes a normal function and runs it on each element of a list.
As a bonus exercise, you might want to think about how you might do the whole thing in one shot as a single fold. It's possible -- and even not too difficult, if you track through what the types of the various arguments to foldr/foldl would have to be!
Additions since the question changed:
Since it looks like you've worked out a solution, I now feel comfortable giving some spoilers. =)
I suggested two possible implementations; one that goes step-by-step, as you suggested, and another that goes all at once. The step-by-step one could look like this:
splits [] = []
splits (0:xs) = [] : splits xs
splits (x:xs) = case splits xs of
[] -> [[x]]
(ys:yss) -> ((x:ys):yss)
groups' = map sum . splits
Or like this:
splits' = groupBy (\x y -> y /= 0)
groups'' = map sum . splits'
The all-at-once version might look like this:
accumulate 0 xs = 0:xs
accumulate n (x:xs) = (n+x):xs
groups''' = foldr accumulate [0]
To check that you understand these, here are a few exercises you might like to try:
What do splits and splits' do with [1,2,3,0,4,5]? [1,2,0,3,4,0]? [0]? []? Check your predictions in ghci.
Predict what each of the four versions of groups (including yours) output for inputs like [] or [1,2,0,3,4,0], and then test your prediction in ghci.
Modify groups''' to exhibit the behavior of one of the other implementations.
Modify groups''' to use foldl instead of foldr.
Now that you've completed the problem on your own, I am showing you a slightly less verbose version. Foldr seems better in my opinion to this problem*, but because you asked for foldl I will show you my solution using both functions.
Also, your example appears to be incorrect, the sum of [5,2,1] is 8, not 7.
The foldr version.
makelist' l = foldr (\x (n:ns) -> if x == 0 then 0:(n:ns) else (x + n):ns) [0] l
In this version, we traverse the list, if the current element (x) is a 0, we add a new element to the accumulator list (n:ns). Otherwise, we add the value of the current element to the value of the front element of the accumulator, and replace the front value of the accumulator with this value.
Step by step:
acc = [0], x = 1. Result is [0+1]
acc = [1], x = 2. Result is [1+2]
acc = [3], x = 5. Result is [3+5]
acc = [8], x = 0. Result is 0:[8]
acc = [0,8], x = 4. Result is [0+4,8]
acc = [4,8], x = 3. Result is [4+3,8]
acc = [7,8], x = 0. Result is 0:[7,8]
acc = [0,7,8], x = 3. Result is [0+3,7,8]
acc = [3,7,8], x = 2. Result is [3+2,7,8]
acc = [5,7,8], x = 1. Result is [5+1,7,8] = [6,7,8]
There you have it!
And the foldl version. Works similarly as above, but produces a reversed list, hence the use of reverse at the beginning of this function to unreverse the list.
makelist l = reverse $ foldl (\(n:ns) x -> if x == 0 then 0:(n:ns) else (x + n):ns) [0] l
*Folding the list from the right allows the cons (:) function to be used naturally, using my method with a left fold produces a reversed list. (There is likely a simpler way to do the left fold version that I did not think of that eliminates this triviality.)
As you already solved it, another version:
subListSums list = reverse $ foldl subSum [0] list where
subSum xs 0 = 0 : xs
subSum (x:xs) n = (x+n) : xs
(Assuming that you have only non-negative numbers in the list)
How do you have multiple statements in haskell?
Here's what I'm trying to do: given a list such as [a,b,c,d], return every other element, so you get [a,c]. I can see the solution, and here's what I have so far:
fact (xs) | length( xs ) `mod` 2 == 1 = head( xs )
| otherwise = fact(tail( xs ))
This works fine the first time around, but then it quits. What I want to be able to say is return the head, and then call fact(tail(xs)) How do I do that?
The function you specified returns only a single element. You'd need to change it to something like:
fact [] = [] -- can't call tail on a list of length 0!
fact (xs) | length( xs ) `mod` 2 == 1 = head( xs ) : fact(tail(xs))
| otherwise = fact(tail( xs ))
You may find it helpful to write out type signatures to help figure out thinkos like this:
fact :: [a] -> [a] -- convert a list of anything to another (shorter) list
However note that this is very slow - O(n^2) in fact, since it's taking length at each step. A much more haskelly solution would use pattern matching to process two elements at a time:
fact :: [a] -> [a]
-- Take the first element of each two-element pair...
fact (x:_:xs) = x:fact xs
-- If we have only one element left, we had an odd-length list.
-- So grab the last element too.
fact [x] = [x]
-- Return nothing if we have an empty list
fact _ = []
There are no statements in Haskell.
You should not abuse parentheses in Haskell. Rather, you should accustom yourself to the language. So your original code should look like
fact xs | length xs `mod` 2 == 1 = head xs
| otherwise = fact (tail xs)
As bdonlan notes, the function you are looking for is really
fact [] = []
fact [x] = [x]
fact (x:_:xs) = x : fact xs
Suppose we have the list [a, b, c, d]. Let us apply the function and fully evaluate the result.
fact [a, b, c, d] = a : fact [c, d]
= a : c : fact []
= a : c : []
= [a, c]
Note that [a, b, c, d] is exactly the same as a : b : c : d : [] because the two ways of representing lists are interpreted interchangeably by the compiler.
Swapping a semaphore
In fact, we can do it following two possible patterns:
[1,2,3,4,..] becomes [1,3,5,7...]
[1,2,3,4,..] becomes [2,4,6,8...]
Both do the same, but they "begin the counting" the opposite way. Let us implement both of them with the same function! Of course, this function must be parametrized according to the "pattern". Two possible patterns exist, thus, we need a boolean for type for parametrization. Implementation: let us use a boolean parameter as a "flag", "semaphore":
module Alternation where
every_second :: [a] -> [a]
every_second = every_second_at False
every_second_at :: Bool -> [a] -> [a]
every_second_at _ [] = []
every_second_at True (x : xs) = x : every_second_at False xs
every_second_at False (x : xs) = every_second_at True xs
We have used an auxiliary function, bookkeeping the "flag/semaphore": it is swapping it accordingly. In fact, this auxiliary function can be regarded as a generalization of the original task. I think, that is what is called a "worker wrapper" function.
Countdown with an index
The task can be generalized even further. Why not to write a much more general function, which can be parametrized by a "modulus" m, and it "harvests" all mth elems of a list?
every_mth 1 [1,2,3,4,...] yields [1,2,3,4...]
every_mth 2 [1,2,3,4,...] yields [1,3,5...]
every_mth 3 [1,2,3,4,...] yields [1,4,7...]
We can use the same ideas as before, just we have to use more complicated a "semaphore": a natural number instead of a boolean. This is a "countdown" parameter, an index i bookkeeping when it is our turn:
module Cycle where
import Nat (Nat)
every_mth :: Nat -> [a] -> [a]
every_mth 0 = undefined
every_mth m # (i + 1) = every_mth_at m i
We use an auxiliary function (worker wrapper), bookkeeping the countdown index i:
every_mth_at :: Nat -> Nat -> [a] -> [a]
every_mth_at _ _ [] = []
every_mth_at m 0 (x : xs) = x : every_mth m xs
every_nth_at m (i + 1) (x : xs) = every_mth_at m i xs
For simplicity's sake, natural number type is "implemented" here as a mere alias:
module Nat (Nat) where
type Nat = Integer
Maybe, in a number theoretic sense, there are also cleaner alternative approaches, not exactly equivalent to the task You specified, but adjusting seems to be straightforward:
let every_mth 1 [0,1,2,3,4,...] yield [0,1,2,3,4,...]
let every_mth 2 [0,1,2,3,4,...] yield [0,2,4,6,8...]
let every_mth 3 [0,1,2,3,4,...] yield [0,3,6,9...]
thus, it is specified here so that it should provide "incidentally" the list of multiples of the parameter, when applied to the lazy list of all natural numbers.
In its implementation, it is worth using numbers as a "zero-based" index. Instead of "every mth", we say: "use i as an index ranging 0, 1, ..., u = m-1, where u denotes the upper limit of the possible indices. This upper index can be a useful parameter in the auxiliary function, which counts down the index.
module Multiple where
import Nat (Nat)
every_mth :: Nat -> [a] -> [a]
every_mth 0 = undefined
every_mth (u + 1) = countdown u
countdown :: Nat -> [a] -> [a]
countdown = countdown_at 0
countdown_at :: Nat -> Nat -> [a] -> [a]
countdown_at _ _ [] = []
countdown_at 0 u (x : xs) = x : countdown_at u u xs
countdown_at (i + 1) u (x : xs) = countdown_at i u xs