Multiply list elements by two or every element by (itself - 1) - haskell

i need to write a function, which takes positive integers list. If list begins with 2, then every element must be multiplied by 2, in other cases every integer n is written n-1 times.
two :: [Int] -> [Int]
i.e:
two [2,1] ==> [4,2]
two [3,2,4] ==> [3,3,2,4,4,4]
multiplyEveryoneByTwo :: [Int] -> [Int]
multiplyEveryoneByTwo [] = []
multiplyEveryoneByTwo [x] = [x*2]
multiplyEveryoneByTwo (x:xs) = (x*2) : multiplyEveryoneByTwo xs
replicateEveryone :: [Int] -> [Int]
replicateEveryone [] = []
replicateEveryone [x] = replicate (x-1) x
replicateEveryone (x:xs) = (replicate (x-1) x) ++ replicateEveryone xs
two :: [Int] -> [Int]
two [x] = if x == 2 then [x*2] else replicate (x-1) x
two (x:xs)
| x == 2 = multiplyEveryoneByTwo (x:xs)
| otherwise = replicateEveryone (x:xs)
I'm stuck now with writing that: if my first element of the list is 2, then recursively multiply every element by 2. I tried to do with extra function multiplyByTwo but it doesn't work.
The else statement is that i need to replicate every element of the list by (itself - 1)
is it correct approach to pass (x:xs) to my helper functions in here | x == 2 = multiplyEveryoneByTwo (x:xs) | otherwise = replicateEveryone (x:xs)

I would suggest separating your problems into two separate functions
multiplyEveryoneByTwo :: [Int] -> [Int]
multiplyEveryoneByTwo ...
replicateEveryone :: [Int] -> [Int]
replicateEveryone ...
After you have these two functions tested and working you can create your weird function that combines them
weirdf [] = ...
weirdf (x:xs)
| x == 2 = multiplyEveryone (...)
|otherwise = replicateEveryone (...)

Not a full answer (since your question was tagged as [homework]), but be careful with your function types. Note the following types:
two :: [Int] -> [Int]
but multiplyByTwo probably has a type like
multiplyByTwo :: Int -> Int
Therefore, you have a typing error when you write
two (x:xs) = if ... then multiplyByTwo x else ...
The type of the if-then-else expression must match the return type of two. Also, check the types of the two branches (the then and the else): do they return an expression of the same type? If not, you have another type error.

Related

Haskell: compare sequences and count the length of the prefix that is common

Im new to haskell and Im writing a function that compares two sequences and reports the length of the prefix they have in common. This is what I have so far but it doesn't work for all cases.
commonLen :: Eq a => [a] -> [a] -> Int
commonLen (x:xs) [] = 0
commonLen (x:xs) (y:ys) | x==y = 1+(commonLen xs ys)
| otherwise = commonLen xs ys
Any ideas where im going wrong? Any help would be appreciated
You should not recurse in case x is different from y. In that case we return 0:
commonLen :: Eq a => [a] -> [a] -> Int
commonLen [] _ = 0
commonLen _ [] = 0
commonLen (x:xs) (y:ys) | x == y = 1 + commonLen xs ys
| otherwise = 0 -- ← return 0
You also can avoid the explicit recursion, and work with:
commonLen :: Eq a => [a] -> [a] -> Int
commonLen xs ys = length (takeWhile id (zipWith (==) xs ys))
here we iterate over both lists concurrently, and compare the elements. We thus make a list of Bools that is True if the elements of the two lists match. Then we use takeWhile to take elements as long as the item is True, and we use length to determine the number of elements in that list. Due to Haskell's laziness, we will never evaluate the entire list if one of the elements differs from the corresponding element in the other list.

basic Haskell: defining sorting function by recursion

So I have slight problem with sorting function. I need to define (using recursion) a function i, that takes as an argument a list of arguments a (this list needs to belong to Ord), which outputs ordered list of elements of type a.
Example:
i [3,2,1] = [1,2,3]
I have managed to come with this solution:
i :: Ord a => [a] -> [a]
i [] = []
i (x:xs)
| x <= head (xs) = x: i xs
| otherwise = i xs : x
But it doesn't compute, outputting many errors. What is wrong?
Let me give you some hints to get you started. First of all, let's fix the formatting:
i :: Ord a => [a] -> [a]
i [] = []
i (x:xs)
| x <= head (xs) = x: i xs
| otherwise = i xs : x
This throws an error which says:
In the first argument of ā€˜(:)ā€™, namely ā€˜i xsā€™
In the expression: i xs : x
Now, this expression i xs : x is problematic. The type of (:) is (:) :: a -> [a] -> [a]. But in your expression you are passing a list instead of a value. What you meant to use was possibly ++. Using that fixes the compile error:
i :: Ord a => [a] -> [a]
i [] = []
i (x:xs)
| x <= head (xs) = x: i xs
| otherwise = i xs ++ [x]
Now, if you try it in ghci, you will get a runtime exception:
ghci> i [3,2,1]
*** Exception: Prelude.head: empty list
Can you guess why ? That's because you haven't handled the case where the list is of length 1. So handling the case will give you this:
i :: Ord a => [a] -> [a]
i [] = []
i (x:[]) = [x]
i (x:xs)
| x <= head (xs) = x: i xs
| otherwise = i xs ++ [x]
Now, you may think that this works:
ghci> i [3,2,1]
[1,2,3]
ghci> i [3,1,2]
[1,2,3]
But it doesn't actually work, because there is a flaw in your algorithm. Just comparing the first two elements of the list won't give you an sorted array.
ghci> i [2,1,3]
[1,3,2]
I hope this is enough to get you started.

Insertion sort in Haskell

I'm doing some exercises on Haskell. First I was asked to define a function insert :: Int -> [Int] -> [Int] so that insert x xs
inserts x into the list xs in such a way that x is bigger than those
elements before it and smaller than or equal to the element that
follow it:
insert :: Int -> [Int] -> [Int]
insert x [] = [x]
insert x (y:ys) = if x < y
then x:y:ys
else y : insert x ys
Now I need to use insert to define a function insertionSort :: [Int] -> [Int]. Here's my attempt:
insertionSort :: [Int] -> [Int]
insertionSort [x] = [x]
insertionSort (x:xs) = insert x insertionSort xs
Error: Couldn't match expected type [Int] with actual type [Int] -> [Int]
Anyone know how I can fix this? Any insight is highly appreciated, thanks.
While learning some sorting algorithms myself, I'd like to give you a few suggestions/improvements to your solution:
Avoid non-exhaustive pattern matching at any case: insertionSort [] = []
Take advantage of instances of Ord over a fixed type
Consider lambda lifting by integrating insert into a where statement in order to get rid of the high-level function and save the argument x
Consider guards over if then else
Which will result in:
insertionSort :: Ord a => [a] -> [a]
insertionSort [] = []
insertionSort [x] = [x]
insertionSort (x:xs) = insert $ insertionSort xs
where insert [] = [x]
insert (y:ys)
| x < y = x : y : ys
| otherwise = y : insert ys
insert x insertionSort xs
is calling insert with three arguments (x,insertionSort,xs).
Probably you want
insert x (insertionSort xs)

Haskell partial sum of a list error

I need to write a function in Haskell that sums the elements of a list until some specific elements stored in another list.
For example partial_add [1,2,3,4,5,6] [2,5] 0 should return [3,12,6].
I have reached this far:
partial_add [] _ count = []
partial_add (a:x) list count | elem a list = count:partial_add x list 0
| otherwise = partial_add x list count+a
(most probably not working properly)
But when I try to run the function (it compiles properly) I get this error:
No instance for (Num [t0]) arising from a use of `it'
In a stmt of an interactive GHCi command: print it
Any idea what's going on?
Given your example, I would write the function something like this:
partialAdd :: [Int] -> [Int] -> [Int]
partialAdd ls seps = foldr f [] ls
where
f a [] = [a]
f a (x:xs)
| a `elem` seps = a:x:xs
| otherwise = (x+a):xs
*Main> partialAdd [1,2,3,4,5,6] [2,5]
[3,12,6]
Btw. I think the solution in your question seems not to work quite the way you specified in your example (or I misunderstood something):
partial_add :: [Int] -> [Int] -> Int -> [Int]
partial_add [] _ count = []
partial_add (a:x) list count | elem a list = count:partial_add x list 0
| otherwise = partial_add x list (count+a)
*Main> partial_add [1,2,3,4,5,6] [2,5] 0
[1,7]
But it is easily fixed to work for your example:
partial_add :: [Int] -> [Int] -> Int -> [Int]
partial_add [] _ count = [count]
partial_add (a:x) list count | elem a list = (count+a):partial_add x list 0
| otherwise = partial_add x list (count+a)
*Main> partial_add [1,2,3,4,5,6] [2,5] 0
[3,12,6]
Note: I am a bit confused by the count parameter since it is ignored in one of the recursive calls, where it is always passed as 0. It should be easy to add its behavior once it's more clear what it does.
Another way to look at this is to first separate the second list* into sublists delimited by (and including) the elements of the first list and then to find the sums of each sublist:
-- | A version of Data.List.splitOneOf that includes the delimiter
splitOneOf' :: Eq a => [a] -> [a] -> [[a]]
splitOneOf' _ [] = [[]]
splitOneOf' delims (x:xs) | x `elem` delims = [x] : splitOneOf' delims xs
splitOneOf' delims (x:xs) | otherwise = let (ys:yss) = splitOneOf' delims xs
in (x:ys) : yss
partialAdd :: (Eq a, Num a) => [a] -> [a] -> [a]
partialAdd delims = map sum . splitOneOf' delims
main :: IO ()
main = print $ partialAdd [2,5] [1,2,3,4,5,6]
gives
[3,12,6]
I think this is a nice example of "bottom up" programming in Haskell.
* I reversed the argument order to match the order used by Data.List.Split.
Thank to your answers i figured it out.
I needed to declare the type of the function and put the parenthesis where they should be.
The code was indeed not working as it should but i fixed that to.
Here is the fixed code:
partial_add :: [Int] -> [Int] -> Int -> [Int]
partial_add [] _ count = [count]
partial_add (a:x) list count | elem a list = (count+a):partial_add x list 0
| otherwise = partial_add x list (count+a)
It may not be the best possible but it worked out for me.

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