I have the following code which
halves each even number in a list:
halfEvens :: [Int] -> [Int]
halfEvens [xs]
| x `mod` 2 == 0 = x `div` 2
| otherwise = x
where x <- xs
And I get the following error:
parse error on input '<-'
I was careful so I respected the indentations...any other ideas what I'm doing wrong?
There are two main issues in your code:
where block defines functions, so, you should use = instead of <-
Your function accepts lists with exactly one element inside
Instead of it I suggest you write separate function halfIfEven:
Prelude> let halfIfEven x = if even x then x `div` 2 else x
Then define halfEvens using map:
Prelude> let halfEvens = map halfIfEven
Prelude> halfEvens [1..10]
[1,1,3,2,5,3,7,4,9,5]
But, of course, you could write this using pattern matching, although it is less readable:
halfIfEven :: Int -> Int
halfIfEven x | even x = x `div` 2
| otherwise = x
halfEvens :: [Int] -> [Int]
halfEvens [] = []
halfEvens (x:xs) = (halfIfEven x):(halfEvens xs)
Related
I'm trying to write a program that takes in two lists and a binary operation and takes each element of one list and applies it to the other using the binary operation. I have it working but not sure how to change it so it works with any binary operator. Here's examples :
myFunction (+) [100,200,300] [4,3,2,1] would return
[96,97,98,99,196,197,198,199,296,297,298,299]
myFunction (+) [100,200,300] [4,3,2,1] would return
[96,97,98,99,196,197,198,199,296,297,298,299]
This is what I have working with specific binary operations
oneEle :: Char -> Integer -> [Integer] -> [Integer]
oneEle a x [] = []
oneEle a x y
| (a == '+') = [p + x | p <- y]
| (a == '-') = [p - x | p <- y]
| (a == '*') = [p * x | p <- y]
| (a == ':') = [p * x | p <- y]
myFunction :: Char -> [Integer] -> [Integer] -> [Integer]
myFunction a [] [] = []
myFunction a [] y = []
myFunction a x [] = []
myFunction a (x:xs) (y:ys) = oneEle a x ([y] ++ ys) ++ myFunction a xs ([y]++ys)
The simplest way is a list comprehension:
myFunction f xs ys = [f x y | x <- xs, y <- ys]
It may not even be worth defining a new function; instead, just inline that content to the call site.
This function is also available from the standard library by the names liftM2 and liftA2.
Can someone else this codes in Haskell:
Doubling Digits
The digits need to be doubled, for this the following function can be defined:
doubleDigits :: [Integer] -> [Integer]
The function doubleDigits must double every other number starting from the right.
The second-to-last number is doubled first, then the fourth-to-last, ..., and so on.
Input: doubleDigits [1,2,3,4,5,6,7]
Output: [1,4,3,8,5,12,7]
toDigitsReverse :: Integer -> [Integer]
toDigitsReverse n = reverse (toDigits n)
-- function to help double every other element of list
doubleDigitsHelper :: [Integer] -> Integer -> [Integer]
doubleDigitsHelper l t
| l == [] = []
| t == 0 = [head l] ++ (doubleDigitsHelper (drop 1 l) 1)
| t == 1 = [2*(head l)] ++ (doubleDigitsHelper (drop 1 l) 0)
-- function to double every other element
doubleDigits :: [Integer] -> [Integer]
doubleDigits l = reverse (doubleDigitsHelper (reverse l) 0)
An alternate approach:
Let's zip the elements of the list with their indices.
[1,2,3,4,5,6,7] `zip` [0..]
We get:
[(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6)]
Then we can map this to the desired result:
let f (x, i) = if even i then x else x * 2 in map f $ [1,2,3,4,5,6,7] `zip` [0..]
And the result is:
[1,4,3,8,5,12,7]
Or written a little bit differently:
doubleDigits lst = map f lst'
where
lst' = lst `zip` [0..]
f (x, i)
| even i = x
| otherwise = x * 2
Because you want to double every other element starting from the right, you can simply reverse the list, zip it with indices, map, then reserve the output.
doubleDigits lst = reverse $ map f lst'
where
lst' = (reverse lst) `zip` [0..]
f (x, i)
| even i = x
| otherwise = x * 2
I would say that first of all there is no point to reverse list, determine if accumulator (t) is even or odd (there are build in functions for that - for example even) and then act accordingly. Next what can imporve the code - use pattern matching instead of == and head/tail calls. Also I've changed the order of the helper function:
-- function to help double every other element of list
doubleDigitsHelper :: Integer -> [Integer] -> [Integer]
doubleDigitsHelper _ [] = []
doubleDigitsHelper t (x:xs) | even t = x : doubleDigitsHelper (t+1) xs
| otherwise = 2*x : doubleDigitsHelper (t+1) xs
-- function to double every other element
doubleDigits :: [Integer] -> [Integer]
doubleDigits = doubleDigitsHelper 0
You could put the alternating functions you want to apply in a list (cycle [id, (*2)]) and apply these to your list using zipWith.
doubleDigits :: Num a => [a] -> [a]
doubleDigits = reverse . zipWith ($) (cycle [id, (*2)]) . reverse
I don't see an elegant way around reversing the list if you want to alternate starting from the right. You could, for example, look at the length of the list first and change the order of the functions based on that, but that would complicate the function a little.
doubleDigits xs = zipWith ($) fs xs
where fs = (if even . length $ xs then tail else id) $ cycle [id, (*2)]
I want to filter a string with a string.
What I want is to use delete every first occurring char.
myFunc :: String -> String -> String
Like:
myFunc "dddog" "bigdddddog" = "biddg"
In "dddog": 3x d, 1x o, 1x g
In the second string it removed 3x d, 1x o and 1x g
So the output: biddg
I can't use filter for it, because it will delete all occurring chars.
And I struggled a long time with it.
Thanks in advance:)
How about
Prelude> :m +Data.List
Prelude Data.List> "bigdddddog" \\ "dddog"
"biddg"
Not the nicest solution, but you can understand easier what's going on:
myfunc :: String -> String -> String
myfunc [] xs = xs
myfunc (x:xs) ys = myfunc xs $ remove x ys
where
remove _ [] = []
remove x (y:ys) = if x == y then ys else y : remove x ys
As you commented, you want to use guards. Do you mean this?
myfunc :: String -> String -> String
myfunc [] xs = xs
myfunc (x:xs) ys = myfunc xs $ remove x ys
remove :: Char -> String -> String
remove _ [] = []
remove x (y:ys)
| x == y = ys
| otherwise = y : remove x ys
some of the other solutions don't seem to produce the same result you posted. I think I have a simple solution that does what you asked for but I may be misunderstanding what you want. All I do in the following code is go though the list and apply 'delete' to every element in the list. It's not exactly efficient but it gets the job done.
import Data.List
myFunc (x:xs) ys = myFunc xs (delete x ys)
myFunc [] ys = ys
There are perhaps more efficient solutions like storing the "to remove" list in a tree with the number of occurences stored as the value then traversing the main list testing to see if the count at that key was still greater than zero. I think that would give you O(n*lg(m)) (where n is the size of the list to be removed from and m is the size of the "to remove" list) rather than O(n*m) as is the case above. This version could also be maid to be lazy I think.
edit:
Here is the tree version I was talking abut using Data.Map. It's a bit complex but should be more efficient for large lists and it is somewhat lazy
myFunc l ys = myFunc' (makeCount l) ys
where makeCount xs = foldr increment (Map.fromList []) xs
increment x a = Map.insertWith (+) x 1 a
decrement x a = Map.insertWith (flip (-)) x 1 a
getCount x a = case Map.lookup x a of
Just c -> c
Nothing -> 0
myFunc' counts (x:xs) = if (getCount x counts) > 0
then myFunc' (decrement x counts) xs
else x : myFunc' counts xs
myFunc' _ [] = []
I am not quite sure about how you want your function to behave, how about this?
import Data.List (isPrefixOf)
myFunc :: String -> String -> String
myFunc _ [] = []
myFunc y x'#(x:xs) | y `isPrefixOf` x' = drop (length y) x'
| otherwise = x : myFilter xs y
This gives the following output in GHCi:
> myFunc "dddog" "bigdddddog"
> "bigdd"
If this is not what you had in mind, please give another input/output example.
I like kaan's elegant solution. In case you meant this...here's one where the "ddd" would only be removed if matched as a whole:
import Data.List (group,isPrefixOf,delete)
f needles str = g (group needles) str where
g needles [] = []
g needles xxs#(x:xs)
| null needle' = [x] ++ g needles xs
| otherwise = let needle = head needle'
in g (delete needle needles) (drop (length needle) xxs)
where needle' = dropWhile (not . flip isPrefixOf xxs) needles
Output:
*Main> f "dddog" "bigdddddog"
"biddg"
*Main> f "dddog" "bdigdogd"
"bdidgd"
No monadic solution yet, there you go:
import Control.Monad.State
myFunc :: String -> State String String
myFunc [] = return ""
myFunc (x:xs) = get >>= f where
f [] = return (x:xs)
f (y:ys) = if y == x then put ys >> myFunc xs
else myFunc xs >>= return . (x:)
main = do
let (a,b) = runState (myFunc "bigdddddog") "dddog" in
putStr a
Using predefined functions from Data.List,
-- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
-- lookup :: (Eq a) => a -> [(a, b)] -> Maybe b
{-# LANGUAGE PatternGuards #-}
import Data.List
picks [] = [] -- http://stackoverflow.com/a/9889702/849891
picks (x:xs) = (x,xs) : [ (y,x:ys) | (y,ys) <- picks xs]
myFunc a b = concat . snd $ mapAccumL f (picks a) b
where
f acc x | Just r <- lookup x acc = (picks r,[])
f acc x = (acc,[x])
Testing:
Prelude Data.List> myFunc "dddog" "bigdddddog"
"biddg"
edit: this is of course a bit more complex than (\\). I'll let it stand as an illustration. There could be some merit to it still, as it doesn't copy the 2nd (longer?) string over and over, for each non-matching character from the 1st (shorter) string, as delete apparently does, used in (\\) = foldl (flip delete).
I'm learning Haskell and wrote this function:
continueWith :: [a] -> a -> [a]
continueWith [] y = repeat y
continueWith (x:xs) y = x : (continueWith xs y)
Now, I don't understand the behavior of GHCi:
GHCi> let x = continueWith [1, 2] 3
x :: [Integer]
GHCi> :sp x
x = _
GHCi> take 3 x
[1,2,3]
it :: [Integer]
GHCi> :sp x
The last sprint doesn't terminate, but I expected the thunk returned by repeat to be only evaluated up to the first cons:
...
GHCi> take 3 x
[1,2,3]
it :: [Integer]
GHCi> :sp x
x = 1 : 2 : 3 : _ <= This is not happening
What am I missing?
The "problem" is that repeat y refers to itself,
repeat y = let ys = y:ys in ys
so once the first cons cell is evaluated, repeat y is completely evaluated. In ASCII art:
(:) <-
/ \ |
y \_|
:sp prints as far as the thing is already evaluated ...
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.