How to add values from two lists (+extra condition) in Haskell - list

I got a problem with this exercise. I've been trying to solve it for a long time searching for stuff, but I am unable to.
Define functions:
addLnat :: [Int] -> [Int] -> [Int]
mulLnat :: [Int] -> [Int] -> [Int]
addLnat adds numbers from two arrays eg.
addLnat [4,5,6] [8,5,2] -> [2,1,9]
as [4+8 gives 2 carry 1, 5+5+1 gives 1 carry 1, 6+2+1 = 9]
Lnat, is a "list natural number", represented as a list of base-10 digits, least significant first. So the number 654 is [4,5,6].
What I got is:
addLnat :: [Int] -> [Int] -> [Int]
addLnat _ [] = []
addLnat [] _ = []
addLnat (x:xs) (y:ys) = (if (x+y) > 9 then x+y-10 else (x+y)):(addLnat xs ys)
I adding number and ignoring carry. Not sure how to solve it.
Any help would be much appreciated.
I have improved the solution as per user5402 comment, so created addLnat' cr xs ys, but when I what to pass carry as a parameter it fails to load - most probable that I am getting the syntax wrong:(
(cr is 0 only for now and it will be replaced by maths).
addLnat' c (x:xs) (y:ys) = d : addLnat' cr xs ys
where d = if c+x+y < 9 then x+y else c+x+y-((quot (c+x+y) 10)*10)
cr = 0
Any ideas?

I am not very good at haskell but maybe this can help ;
add::[Int]->[Int]->[Int]
add x y = add' 0 x y
There we define a function add that will use add' to add two lists The main idea is to "save" carry and carefully work with corner cases. Here carry is saved in "variable" rest
add'::Int->[Int]->[Int]->[Int]
add' 0 x [] = x
add' rest (x:[]) (y:[]) = [(r `mod` 10),(r `div` 10)]
where r = x+y+rest
add' y (x:xs) [] = add' (r `div` 10) ((r `mod` 10):xs) []
where r = x+y
add' rest (x:xs) (y:ys) = (r `mod` 10) : (add' (r `div` 10) xs ys)
where r = x+y+rest
List x must be bigger than list y but that's not a problem
add [5,7,8] [4,3,2] => [9,0,1,1] (correct)
add [1,2,3] [4,5,6] => [5,7,9,0] (correct)

You need to write a version of addLnat which accepts a carry parameter:
addLnat' c (x:xs) (y:ys) = d : addLnat c' xs ys
where d = if c+x+y > 9 then ... else ...
c' = ... the next carry bit ...
There are a lot more details and corner cases to consider, but this is the basic idea.
Finally,
addLnat xs ys = addLnat' 0 xs ys -- initially the carry is 0

Related

F# - splitting list into tuple of odd-even lists (by element, not position)

Example: split [1;3;2;4;7;9];;
Output: ([1;3;7;9], [2;4])
I'm new to F# and I can't figure it out.
Can't use the partition built in function.
This is what I have so far:
let rec split xs =
match xs with
| [] -> [], []
| xs -> xs, []
| xh::xt -> let odds, evens = split xt
if (xh % 2) = 0 then xh::odds, xh::evens
else xh::odds, evens
Fixed code:
let rec split xs =
match xs with
| [] -> [], []
| xh::xt -> let odds, evens = split xt
if (xh % 2) = 0 then odds, xh::evens
else xh::odds, evens
*Thanks to #TheInnerLight for pointing out my errors: unreachable case and unnecessarily modifying odds
You can use the built-in List.partition function
let splitOddEven xs =
xs |> List.partition (fun x -> x % 2 <> 0)
splitOddEven [1;3;2;4;7;9];;
val it : int list * int list = ([1; 3; 7; 9], [2; 4])
If you want a recursive implementation, I'd probably go for a tail recursive implementation like this:
let splitOddEven xs =
let rec splitOddEvenRec oddAcc evenAcc xs =
match xs with
| [] -> oddAcc, evenAcc
| xh::xt ->
if (xh % 2) = 0 then splitOddEvenRec oddAcc (xh :: evenAcc) xt
else splitOddEvenRec (xh :: oddAcc) evenAcc xt
splitOddEvenRec [] [] xs
splitOddEven [1;3;2;4;7;9]
Note that this will give you the two resulting lists in reverse order so you might wish to reverse them yourself.

Delete Second Occurence of Element in List - Haskell

I'm trying to write a function that deletes the second occurrence of an element in a list.
Currently, I've written a function that removes the first element:
removeFirst _ [] = []
removeFirst a (x:xs) | a == x = xs
| otherwise = x : removeFirst a xs
as a starting point. However,I'm not sure this function can be accomplished with list comprehension. Is there a way to implement this using map?
EDIT: Now I have added a removeSecond function which calls the first
deleteSecond :: Eq a => a -> [a] -> [a]
deleteSecond _ [] = []
deleteSecond a (x:xs) | x==a = removeFirst a xs
| otherwise = x:removeSecond a xs
However now the list that is returned removes the first AND second occurrence of an element.
Well, assuming you've got removeFirst - how about searching for the first occurence, and then using removeFirst on the remaining list?
removeSecond :: Eq a => a -> [a] -> [a]
removeSecond _ [] = []
removeSecond a (x:xs) | x==a = x:removeFirst a xs
| otherwise = x:removeSecond a xs
You could also implement this as a fold.
removeNth :: Eq a => Int -> a -> [a] -> [a]
removeNth n a = concatMap snd . scanl go (0,[])
where go (m,_) b | a /= b = (m, [b])
| n /= m = (m+1, [b])
| otherwise = (m+1, [])
and in action:
λ removeNth 0 1 [1,2,3,1]
[2,3,1]
λ removeNth 1 1 [1,2,3,1]
[1,2,3]
I used scanl rather than foldl or foldr so it could both pass state left-to-right and work on infinite lists:
λ take 11 . removeNth 3 'a' $ cycle "abc"
"abcabcabcbc"
Here is an instinctive implementation using functions provided by List:
import List (elemIndices);
removeSecond x xs = case elemIndices x xs of
(_:i:_) -> (take i xs) ++ (drop (i+1) xs)
_ -> xs
removeNth n x xs = let indies = elemIndices x xs
in if length indies < n
then xs
else let idx = indies !! (n-1)
in (take idx xs) ++ (drop (idx+1) xs)
Note: This one cannot handle infinite list, and its performance may not be good for very large list.

Haskell <<loop>>

With getIndex xs y I want the index of the first sublist in xs whose length is greater than y.
The output is:
[[],[4],[4,3],[3,5,3],[3,5,5,6,1]]
aufgabe6: <<loop>>
why getIndex does not work?
import Data.List
-- Die Sortierfunktion --
myCompare a b
| length a < length b = LT
| otherwise = GT
sortList :: [[a]] -> [[a]]
sortList x = sortBy myCompare x
-- Die Indexfunktion --
getIndex :: [[a]] -> Int -> Int
getIndex [] y = 0
getIndex (x:xs) y
| length x <= y = 1 + getIndex xs y
| otherwise = 0
where (x:xs) = sortList (x:xs)
main = do
print (sortList [[4],[3,5,3],[4,3],[3,5,5,6,1],[]])
print (getIndex [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 2)
Getting it to terminate
The problem is in this case
getIndex (x:xs) y
| length x <= y = 1 + getIndex xs y
| otherwise = 0
where (x:xs) = sortList (x:xs)
You're confusing which (x:xs) is which. You should instead do
getIndex zs y
| length x <= y = 1 + getIndex xs y
| otherwise = 0
where (x:xs) = sortList zs
giving
Main> main
[[],[4],[4,3],[3,5,3],[3,5,5,6,1]]
3
*Main> getIndex [[],[2],[4,5]] 1
2
*Main> getIndex [[],[2],[4,5]] 5
3
This gives you the number of the first list of length at least y in the sorted list, which actually answers the question "How many lists are of length at most y in the original?"
How can we find out other facts?
If you want position from the original list, you can tag the entries with their position, using zip:
*Main> zip [1..] [[4],[3,5,3],[4,3],[3,5,5,6,1],[]]
[(1,[4]),(2,[3,5,3]),(3,[4,3]),(4,[3,5,5,6,1]),(5,[])]
Let's make a utility function for working with those:
hasLength likeThis (_,xs) = likeThis (length xs)
We can use it like this:
*Main> hasLength (==4) (1,[1,2,3,4])
True
*Main> filter (hasLength (>=2)) (zip [1..] ["","yo","hi there","?"])
[(2,"yo"),(3,"hi there")]
Which means it's now easy to write a function that gives you the index of the first list of length longer than y:
whichIsLongerThan xss y =
case filter (hasLength (>y)) (zip [1..] xss) of
[] -> error "nothing long enough" -- change this to 0 or (length xss + 1) if you prefer
(x:xs) -> fst x
This gives us
*Main> whichIsLongerThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 2
2
*Main> whichIsLongerThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 3
4
*Main> whichIsLongerThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 0
1
Shorter?
but we can do similar tricks:
whichIsShorterThan xss y =
case filter (hasLength (<y)) (zip [1..] xss) of
[] -> error "nothing short enough" -- change this to 0 or (length xss + 1) if you prefer
(x:xs) -> fst x
so you get
*Main> whichIsShorterThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 2
1
*Main> whichIsShorterThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 1
5
*Main> whichIsShorterThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 0
*** Exception: nothing short enough
Generalised
Let's pull out the common theme there:
whichLength :: (Int -> Bool) -> [[a]] -> Int
whichLength likeThis xss =
case filter (hasLength likeThis) (zip [1..] xss) of
[] -> error "nothing found" -- change this to 0 or (length xss + 1) if you prefer
(x:xs) -> fst x
so we can do
*Main> whichLength (==5) [[4],[3,5,3],[4,3],[3,5,5,6,1],[]]
4
*Main> whichLength (>2) [[4],[3,5,3],[4,3],[3,5,5,6,1],[]]
2
Do you mean index of the firs sublist with length > y? If that's not the goal (and < y is), then
length x <= y = 1 + getIndex xs y
should be
length x >= y = 1 + getIndex xs y
Also, (x:xs) = sortList (x:xs) is bottom, since it will never end. If you want to sort it somehow, you might follow AndrewC's solution.
let (and where) bindings in Haskell are recursive: LHS and RHS both belong (and thus refer to) to the same new scope. Your code is equivalent to
........
getIndex (x:xs) y =
let -- new, extended scope, containing definitions for
(x:xs) = a -- new variables x, xs, a ... the original vars x, xs
a = sortList a -- are inaccessible, __shadowed__ by new definitions
in -- evaluated inside the new, extended scope
if length x <= y -- x refers to the new definition
then 1 + getIndex xs y
else 0
When the value of x is demanded by length, its new definition (x:xs) = a demands the value of a, which is directly defined in terms of itself, a = sortList a:
a = sortList a
= sortList (sortList a)
= sortList (sortList (sortList a))
= sortList (sortList (sortList (sortList a)))
= ....
A black hole.

Comparing lists in Haskel

I have to define a function called zeros which takes input of two lists and returns a boolean which returns True if the number 0 appears the same amount of times in each list and false otherwise.
This is the last question in my homework and and I have managed to solve the question get it to work but I wondered if anybody can spot ways in which to reduce the amount of code, any ideas are appreciated. My code so far is as follows:
x :: Int
x = 0
instances::[Int]->Int
instances [] = 0
instances (y:ys)
| x==y = 1+(instances ys)
| otherwise = instances ys
zeros :: [Int] -> [Int] -> Bool
zeros [] [] = False
zeros x y
| ((instances x) == (instances y)) = True
| otherwise = False
Without giving too much away, since this is homework, here are a few hints.
Do you know about list comprehensions yet? They would be useful in this case. For example, you could combine them with an if expression to do something like this:
*Main> let starS s = [if c == 's' then '*' else ' ' | c <- s]
*Main> starS "schooners"
"* *"
You can even use them to do filtering. For example:
*Main> let findFives xs = [x | x <- xs, x == 5]
*Main> findFives [3,7,5,6,3,4,5,7,5,5]
[5,5,5,5]
Neither of these is a complete answer, but it shouldn't be hard to see how to adapt these structures to your situation.
You should also think about whether you actually need a guard here! For example, here's a function written with a guard in the same style as yours:
lensMatch [] [] = True
lensMatch xs ys
| ((length xs) == (length ys)) = True
| otherwise = False
Here's a function that does the same thing!
lensMatch' xs ys = length xs == length ys
You can see that they are the same; testing the first:
*Main> lensMatch [1..4] [1..4]
True
*Main> lensMatch [1..4] [1..5]
False
*Main> lensMatch [] [1..5]
False
*Main> lensMatch [] []
True
And testing the second:
*Main> lensMatch' [1..4] [1..4]
True
*Main> lensMatch' [1..4] [1..5]
False
*Main> lensMatch' [] [1..5]
False
*Main> lensMatch' [] []
True
Finally, I agree very strongly with sblom's comment above; zeros [] [] should be True! Think about the following statement: "For each item x in set s, x > 0". If set s is empty, then the statement is true! It's true because there are no items in s at all. This seems to me like a similar situation.
I can't believe nobody has suggested to use foldr yet. Not the shortest or best definition, but IMO the most educational:
instances :: Eq a => a -> [a] -> Int
instances n = foldr incrementIfEqual 0
where incrementIfEqual x subtotal
| x == n = subtotal + 1
| otherwise = subtotal
zeros :: Num a => [a] -> [a] -> Bool
zeros xs ys = instances 0 xs == instances 0 ys
Though for a really brief definition of instances, what I came up with is basically the same as Abizern:
instances :: Eq a => a -> [a] -> Int
instances x = length . filter (==x)
Have you thought of doing this in one pass by filtering each list to get just the zeroes and then comparing the length of the lists to see if they are equal?
zeroCompare xs ys = cZeroes xs == cZeroes ys
where
cZeroes as = length $ filter (== 0) as
Instead of length and filter, you can take the result of a predicate p, convert it to 0 or 1, and sum the result:
count p = sum . map (fromEnum.p)
--or
import Data.List
count p = foldl' (\x -> (x+).fromEnum.p) 0
In your case, p is of course (==0). Converting Bool to Int using fromEnum is a very useful trick.
Another idea would be to deal with both list simultaneously, which is a little bit lengthy, but easy to understand:
zeros xs ys = cmp xs ys == 0 where
cmp (0:xs) ys = cmp xs ys + 1
cmp xs (0:ys) = cmp xs ys - 1
cmp (_:xs) ys = cmp xs ys
cmp xs (_:ys) = cmp xs ys
cmp [] [] = 0
I would break the problem down into smaller problems involving helper functions.
This is how I would break it down:
Main function to compare two counts
Count helper function
First: You need a way to count the amount of zeroes in a list. For example, I would approach this by doing the following if searching for the number of 0 in an integer list:
count :: [Int] -> Int
count xs = foldl (\count num -> if num == 0 then (count + 1) else count) 0 xs
Second: You need a way to compare the count of two lists. Essentially, you need a function that takes two lists in as parameters, calculates the count of each list, and then returns a boolean depending on the result. For example, if each list is an int list, corresponding with my count example above:
equalZeroes :: [Int] -> [Int] -> Bool
equalZeroes x y = (count x) == (count y)
You could also define count under the where keyword inside the equalZeroes function like so:
equalZeroes :: [Int] -> [Int] -> Bool
equalZeroes x y = (count x) == (count y)
where
count :: [Int] -> Int
count xs = foldl (\count num -> if num == 0 then (count + 1) else count) 0 xs
When running this code, calling the function as so would get the desired boolean values returned:
equalZeroes [0,1,4,5,6] [1,4,5,0,0]
-> False
equalZeroes [0,1,4,5,6] [1,4,5,0]
-> True

Remove elements by index in haskell

I'm new in haskell and I'm looking for some standard functions to work with lists by indexes.
My exact problem is that i want to remove 3 elements after every 5. If its not clear enough here is illustration:
OOOOOXXXOOOOOXXX...
I know how to write huge function with many parameters, but is there any clever way to do this?
Two completely different approaches
You can use List.splitAt together with drop:
import Data.List (splitAt)
f :: [a] -> [a]
f [] = []
f xs = let (h, t) = splitAt 5 xs in h ++ f (drop 3 t)
Now f [1..12] yields [1,2,3,4,5,9,10,11,12]. Note that this function can be expressed more elegantly using uncurry and Control.Arrow.second:
import Data.List (splitAt)
import Control.Arrow (second)
f :: [a] -> [a]
f [] = []
f xs = uncurry (++) $ second (f . drop 3) $ splitAt 5 xs
Since we're using Control.Arrow anyway, we can opt to drop splitAt and instead call in the help of Control.Arrow.(&&&), combined with take:
import Control.Arrow ((&&&))
f :: [a] -> [a]
f [] = []
f xs = uncurry (++) $ (take 5 &&& (f . drop 8)) xs
But now it's clear that an even shorter solution is the following:
f :: [a] -> [a]
f [] = []
f xs = take 5 xs ++ (f . drop 8) xs
As Chris Lutz notes, this solution can then be generalized as follows:
nofm :: Int -> Int -> [a] -> [a]
nofm _ _ [] = []
nofm n m xs = take n xs ++ (nofm n m . drop m) xs
Now nofm 5 8 yields the required function. Note that a solution with splitAt may still be more efficient!
Apply some mathematics using map, snd, filter, mod and zip:
f :: [a] -> [a]
f = map snd . filter (\(i, _) -> i `mod` 8 < (5 :: Int)) . zip [0..]
The idea here is that we pair each element in the list with its index, a natural number i. We then remove those elements for which i % 8 > 4. The general version of this solution is:
nofm :: Int -> Int -> [a] -> [a]
nofm n m = map snd . filter (\(i, _) -> i `mod` m < n) . zip [0..]
Here is my take:
deleteAt idx xs = lft ++ rgt
where (lft, (_:rgt)) = splitAt idx xs
You can count your elements easily:
strip' (x:xs) n | n == 7 = strip' xs 0
| n >= 5 = strip' xs (n+1)
| n < 5 = x : strip' xs (n+1)
strip l = strip' l 0
Though open-coding looks shorter:
strip (a:b:c:d:e:_:_:_:xs) = a:b:c:d:e:strip xs
strip (a:b:c:d:e:xs) = a:b:c:d:e:[]
strip xs = xs
Since nobody did a version with "unfoldr", here is my take:
drop3after5 lst = concat $ unfoldr chunk lst
where
chunk [] = Nothing
chunk lst = Just (take 5 lst, drop (5+3) lst)
Seems to be the shortest thus far
the take and drop functions may be able to help you here.
drop, take :: Int -> [a] -> [a]
from these we could construct a function to do one step.
takeNdropM :: Int -> Int -> [a] -> ([a], [a])
takeNdropM n m list = (take n list, drop (n+m) list)
and then we can use this to reduce our problem
takeEveryNafterEveryM :: Int -> Int -> [a] -> [a]
takeEveryNafterEveryM n m [] = []
takeEveryNafterEveryM n m list = taken ++ takeEveryNafterEveryM n m rest
where
(taken, rest) = takeNdropM n m list
*Main> takeEveryNafterEveryM 5 3 [1..20]
[1,2,3,4,5,9,10,11,12,13,17,18,19,20]
since this is not a primitive form of recursion, it is harder to express this as a simple fold.
so a new folding function could be defined to fit your needs
splitReduce :: ([a] -> ([a], [a])) -> [a] -> [a]
splitReduce f [] = []
splitReduce f list = left ++ splitReduce f right
where
(left, right) = f list
then the definition of takeEveryNafterEveryM is simply
takeEveryNafterEveryM2 n m = splitReduce (takeNdropM 5 3)
This is my solution. It's a lot like #barkmadley's answer, using only take and drop, but with less clutter in my opinion:
takedrop :: Int -> Int -> [a] -> [a]
takedrop _ _ [] = []
takedrop n m l = take n l ++ takedrop n m (drop (n + m) l)
Not sure if it'll win any awards for speed or cleverness, but I think it's pretty clear and concise, and it certainly works:
*Main> takedrop 5 3 [1..20]
[1,2,3,4,5,9,10,11,12,13,17,18,19,20]
*Main>
Here is my solution:
remElements step num=rem' step num
where rem' _ _ []=[]
rem' s n (x:xs)
|s>0 = x:rem' (s-1) num xs
|n==0 = x:rem' (step-1) num xs
|otherwise= rem' 0 (n-1) xs
example:
*Main> remElements 5 3 [1..20]
[1,2,3,4,5,9,10,11,12,13,17,18,19,20]
myRemove = map snd . filter fst . zip (cycle $ (replicate 5 True) ++ (replicate 3 False))