swap two elements in Haskell by value - haskell

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.

Related

Haskell, taking a list of pairs (value,index) and making it a single list [Int]

I am fairly new at Haskell and have been trying to solve this.
I have been trying to take a list of pairs and condense it down to a single list
For example if I had the pairs:
[(2,0),(4,5),(3,10)]
The list should return
[2,0,0,0,0,4,0,0,0,0,3]
The idea is that the first element of the pair is the value and the second value is the index.
Here is what I have tried so far:
finalList :: [(Int,Int)] -> [Int]
finalList ((x,y): xs) = replicate y 0 ++ [x] ++ finalList xs
finalList _ = []
However with this issue I am not getting the desired padding of 0s that I would like to have . I am instead getting something like:
[6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,12]
Any help would be greatly appreciated! Thanks!
I will provide a hint. I will also assume that the indices in the input list are in increasing order.
A possible approach is to first define an auxiliary function that takes one more argument, an "index" counting how many elements we have produces so far. Here is a sketch of a part of the code you might use.
f :: [(Int,Int)] -> Int -> [Int]
f [] _ = ... -- base case
f ((value, pos):xs) ix
| ix == pos = value : ... -- here we recurse
| otherwise = 0 : ... -- here we recurse too
Roughly put, the logic above is: keep track of the current position ix: if the position is the wanted one pos, emit value. Otherwise emit 0 as a filler.
In both cases we recurse, and we need to increment the current position ix. The current position is will be initially set to zero as follows:
finalList :: [(Int,Int)] -> [Int]
finalList xs = f xs 0
Note that when we recurse, we also need to understand what to do with the input list. I will leave that to you.

Haskell beginners level function implementation [duplicate]

This question already has answers here:
Eq => function in Haskell
(2 answers)
Closed 3 years ago.
I am new to Haskell and am trying to write quite an easy function which gathers each repeated consecutive elements under separate sub-lists, For example:
f :: Eq a => [a] -> [[a]]
So:
f [] = []
f [3] = [[3]]
f [1,1,1,3,2,2,1,1,1,1] = [[1,1,1],[3],[2,2],[1,1,1,1]]
I thought about this function:
f :: Eq a => [a] -> [[a]]
f [] = []
f (x:[]) = [[x]]
f (x:x':xs) = if x == x' then [[x, x']] ++ (f (xs))
else [[x]] ++ (f (xs))
It seems to not work well since when it arrives to the last element, it wants to compare it to its consecutive, which clearly does not exist.
I would like to receive a simple answer (beginner level) that will not be too different than mine, correcting my code will be the best.
Thanks in advance.
The problem isn't really what you said, it's just that you only hard-coded the cases that either one or two consecutive elements are equal. Actually you want to ground together an arbitrary number of equal consecutives. IOW, for every element, you pop off as many following ones as are equal.
Generally, splitting of the head-part of a list which fulfills some condition is what the span function does. In this case, the condition it's supposed to check is being equal to the element you already removed. That's written thus:
f [] = []
f (x:xs) = (x:xCopies) : f others
where (xCopies,others) = span (==x) xs
Here, x:xCopies puts together the chunk of elements equal to x (with x itself on front), use that as the heading chunk-list of the result, and then you recurse over all the elements that remain.
Your problem is that both halves of your if have the same structure: they cons exactly one element onto the front of the recursive call. This can't be right: sometimes you want to add an element to the front of the list, and other times you want to combine your element with what's already in the recursive call.
Instead, you need to pattern-match on the recursive call to get the first item in the recursive result, and then prepend to that when the first two items match.
f :: Eq a => [a] -> [[a]]
f [] = []
f [x] = [[x]]
f (x:xs#(y:_)) | x == y = (x:head):more
| otherwise = [x]:result
where result#(head:more) = f xs

Error on the resulting list of my elemIndices function

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

“replace” a 3-tuple

I have the following list (it’s a length 2 list, but in my assignment I have a length +n list)
xxs = [(11,22,[(33,33,33),(44,44,44)]),(55,66,[(77,77,77),(88,88,88)])]
I’m trying to “replace” one 3-tuple (p1 or p2 or p3 or p4 from the image bellow) by list index (n) and by sub-list index (p).
The function, at the end, should be like:
fooo newtuple n p = (…)
For example: (replace p3 for (98,98,98):
fooo (98,98,98) 2 1
[(11, 22, [(33,33,33) , (44,44,44)]) , (55, 66, [(98,98,98),(88,88,88)])]
I planned the code like following this steps:
Access the pn that I want to change. I manage to achieve it by:
fob n p = ((aux2 xxs)!!n)!!p
where aux2 [] = []
aux2 ((_,_,c):xs) = c:aux2 xs
“replace” the 3-tuple. I really need some help here. I’m stuck. the best code (in my head it makes some sense) that I’ve done: (remember: please don’t be too bad on my code, I’ve only been studying Haskell only for 5 weeks)
foo n p newtuple = fooAux newtuple fob
where fooAux _ [] = []
fooAux m ((_):ds) = m:ds
fob n p = ((aux2 xxs)!!n)!!p
where aux2 [] = []
aux2 ((_,_,c):xs) = c:aux2 xs
Finally I will put all back together, using splitAt.
Is my approach to the problem correct? I really would appreciate some help on step 2.
I'm a bit new to Haskell too, but lets see if we can't come up with a decent way of doing this.
So, fundamentally what we're trying to do is modify something in a list. Using functional programming I'd like to keep it a bit general, so lets make a function update.
update :: Int -> (a -> a) -> [a] -> [a]
update n f xs = pre ++ (f val) : post
where (pre, val:post) = splitAt n xs
That will now take an index, a function and a list and replace the nth element in the list with the result of the function being applied to it.
In our bigger problem, however, we need to update in a nested context. Luckily our update function takes a function as an argument, so we can call update within that one, too!
type Triple a = (a,a,a)
type Item = (Int, Int, [Triple Int])
fooo :: Triple Int -> Int -> Int -> [Item] -> [Item]
fooo new n p = update (n-1) upFn
where upFn (x,y,ps) = (x,y, update (p-1) objFn ps)
objFn _ = new
All fooo has to do is call update twice (once within the other call) and do a little "housekeeping" work (putting the result in the tuple correctly). The (n-1) and (p-1) were because you seem to be indexing starting at 1, whereas Haskell starts at 0.
Lets just see if that works with our test case:
*Main> fooo (98,98,98) 2 1 [(11,22,[(33,33,33),(44,44,44)]),(55,66,[(77,77,77),(88,88,88)])]
[(11,22,[(33,33,33),(44,44,44)]),(55,66,[(98,98,98),(88,88,88)])]
First, we need a general function to map a certain element of a list, e.g.:
mapN :: (a -> a) -> Int -> [a] -> [a]
mapN f index list = zipWith replace list [1..] where
replace x i | i == index = f x
| otherwise = x
We can use this function twice, for the outer list and the inner lists. There is a little complication as the inner list is part of a tuple, so we need another helper function:
mapTuple3 :: (c -> c) -> (a,b,c) -> (a,b,c)
mapTuple3 f (x,y,z) = (x,y,f z)
Now we have everything we need to apply the replace function to our use case:
fooo :: Int -> Int -> (Int,Int,Int) -> [(Int,Int,[(Int,Int,Int)])]
fooo n p newTuple = mapN (mapTuple3 (mapN (const newTuple) p)) n xxs
Of course in the inner list, we don't need to consider the old value, so we can use const :: a -> (b -> a) to ignore that argument.
So you've tried using some ready-made function, (!!). It could access an item in a list for you, but forgot its place there, so couldn't update. You've got a solution offered, using another ready-made function split, that tears a list into two pieces, and (++) which glues them back into one.
But to get a real feel for it, what I suspect your assignment was aiming at in the first place (it's easy to forget a function name, and it's equally easy to write yourself a new one instead), you could try to write the first one, (!!), yourself. Then you'd see it's real easy to modify it so it's able to update the list too.
To write your function, best think of it as an equivalence equation:
myAt 1 (x:xs) = x
myAt n (x:xs) | n > 1 = ...
when n is zero, we just take away the head element. What do we do when it's not? We try to get nearer towards the zero. You can fill in the blanks.
So here we returned the element found. What if we wanted to replace it? Replace it with what? - this calls another parameter into existence,
myRepl 1 (x:xs) y = (y:xs)
myRepl n (x:xs) y | n > 1 = x : myRepl ...
Now you can complete the rest, I think.
Lastly, Haskell is a lazy language. That means it only calls into existence the elements of a list that are needed, eventually. What if you replace the 7-th element, but only first 3 are later asked for? The code using split will actually demand the 7 elements, so it can return the first 3 when later asked for them.
Now in your case you want to replace in a nested fashion, and the value to replace the old one with is dependent on the old value: newVal = let (a,b,ls)=oldVal in (a,b,myRepl p ls newtuple). So indeed you need to re-write using functions instead of values (so that where y was used before, const y would go):
myUpd 1 (x:xs) f = (f x:xs)
myUpd n ... = ...
and your whole call becomes myUpd n xxs (\(a,b,c)->(a,b,myUpd ... (const ...) )).

List comprehension: making lists of lists

hi im trying to make a function in haskell that takes a number a makes a partion of it using lists i.e. for number 4 it would create [[1,1,1,1],[1,1,2],[1,3],[2,2],[4]]. I was thinking of using list comprehension for this where it would create list x and then create further lists using numbers from [1...n] (n being the partition number I would want) where the sum of the list created would be equal to n.
The code I have created so far is-
partions (n:xs) = [[x|x<-[1...n], sum[x]==n]]|xs<-[1..]]
but obiviously it doesnt work, any suggestions?
thanks.
I suggest trying recursion: To obtain the partitions of n, iterate over the numbers i = 1 to n, and recursively generate the partitions of (n-i), the base case being that the only partition of 1 is 1 itself, and the partition of 0 is the empty list.
How about this...
import Data.List (nub, sort)
parts :: Int -> [[Int]]
parts 0 = []
parts n = nub $ map sort $ [n] : [x:xs | x <- [1..n`div`2], xs <- parts(n - x)]
Trying it:
*Main Control.Monad> forM [1..5] (print . parts)
[[1]]
[[2],[1,1]]
[[3],[1,2],[1,1,1]]
[[4],[1,3],[1,1,2],[1,1,1,1],[2,2]]
[[5],[1,4],[1,1,3],[1,1,1,2],[1,1,1,1,1],[1,2,2],[2,3]]
I think it's correct, if not efficient.
I found it helpful to define an auxiliary function, partitionsCap, which does not let any of the items be larger than a given value. Used recursively, it can be used to only produce the monotonically decreasing results you want (i.e. no [1,3,1] when you already have [1,1,3]):
partitions :: Int -> [[Int]]
partitions n = partitionsCap n n
partitionsCap :: Int -> Int -> [[Int]]
partitionsCap cap n
| n < 0 = error "partitions: negative number"
| n == 0 = [[]]
| n > 0 = [i : p | i <- [hi,hi-1..1], p <- partitionsCap i (n-i)]
where hi = min cap n
At the heart of the algorithm is the idea that, when partitioning N, you take i from n down to 1, and prepend i to the partitions of n-i. Simplified:
concat [map (i:) $ partitions (n-i) | i <- [n,n-1..1]]
but wrong:
> partitions 3
[[3],[2,1],[1,2],[1,1,1]]
We want that [1,2] to go away. Hence, we need to cap the partitions we're prepending to so they won't go above i:
concat [map (i:) $ partitionsCap i (n-i) | i <- [hi,hi-1..1]]
where hi = min cap n
Now, to clean it up: that concat and map so close together got my attention. A little background: list comprehensions and the list monad are very closely related, and concatMap is the same as >>= with its arguments flipped, in the list monad. So I wondered: can those concat and map somehow turn into a >>=, and can that >>= somehow sweet-talk its way into the list comprehension?
In this case, the answer is yes :-)
[i : p | i <- [hi,hi-1..1], p <- partitionsCap i (n-i)]
where hi = min cap n
I'm a little rusty with Haskell, but maybe the following code can guide you to find the solution.
parts :: Int -> Int -> [[Int]]
parts 0 p = [[]]
parts x p = [(y:ys) | y <-[p..x], ys <- (parts (x - y) y)]
And then you would have to call parts with x = n, and p = 1.
EDIT
I've fixed the base case when x equals 0 to return a list with a single item, being that item an empty list. Now it works fine :)

Resources