Given two lists of digits such as [1, 2, 0] = 120 and [1,0,1] = 101, my function sub should return the list [1, 9] = 19 but the function is returning [2, -1] instead. How do I solve this carry problem? It works fine when there isn't a carry and it only receives positive numbers.
Here's the code I have:
sub_Carry :: Integer -> [Integer] -> [Integer] -> [Integer]
sub_Carry c x []
| c == 0 = x
| otherwise = sub_Carry 0 [c] x
sub_Carry c [] x
| c == 0 = x
| otherwise = sub_Carry 0 x [c]
sub_Carry c (x : xs) (y : ys) = (x - y) : sub_Carry c xs ys
sub :: [Integer] -> [Integer] -> [Integer]
sub op1 op2
| to_Integer(op1) == to_Integer(op2) = [0]
| to_Integer(op1) > to_Integer(op2) = drop_Zeros (reverse (sub_Carry 0 (reverse op1) (reverse op2)))
| otherwise = [-1] ++ drop_Zeros (reverse (sub_Carry 0 (reverse op1) (reverse op2)))
Other considerations:
I've have other utility functions such as to_Integer that converts the list into it's correspondent integer, drop_Zeros that removes zeros to the right of the list ([0, 1, 0] = [1, 0])
in the case the result is a negative number it should return the list with -1 at the head ([1, 0, 0] - [1, 0, 1] = [-1, 1])
I noticed that you don't use the parameter c for carrying. It is the central point of the exercise. It is also necessary to solve the case when the list of a parameter y ends earlier than x. My program works only for positive results. So I also modified the function sub to reverse parameters when op1 < op2. Now there should be always a positive result, which you then negate using the constant -1.
sub_Carry :: Integer -> [Integer] -> [Integer] -> [Integer]
sub_Carry 0 [] [] = []
sub_Carry c x [] = sub_Carry c x [0]
sub_Carry c (x : xs) (y : ys)
| (x - y - c) < 0 = (10 + x - y - c) : sub_Carry 1 xs ys
| otherwise = (x - y - c ) : sub_Carry 0 xs ys
sub :: [Integer] -> [Integer] -> [Integer]
sub op1 op2
| to_Integer(op1) == to_Integer(op2) = [0]
| to_Integer(op1) > to_Integer(op2) = drop_Zeros (reverse (sub_Carry 0 (reverse op1) (reverse op2)))
| otherwise = [-1] ++ drop_Zeros (reverse (sub_Carry 0 (reverse op2) (reverse op1)))
Related
I think about the function to count all positives numbers in a list. My idee was
countPositives :: [Int] -> Int
countPositives xs = length [ x | x <- xs, x > 0]
That code work, but I thinking it is possible to write with the filter function or with guards. Is it possilbe and if yes, how can I write it?
Both approaches would be pretty straightforward.
Filter the collection and count it's length:
countPositives' :: [Int] -> Int
countPositives' = length.filter (>0)
With guards:
countPositives'' :: [Int] -> Int
countPositives'' [] = 0
countPositives'' (x:xs) | x > 0 = 1 + countPositives'' xs
| otherwise = countPositives'' xs
As yet another alternative, use a fold:
ghci> lst = [1, 2, 4, 7, -2, -3, 0, 8]
ghci> foldr (\x i -> if x > 0 then i + 1 else i) 0 lst
5
I wrote a small code, which counts of characters or a numbers in a list and how many times. for example howManyTimes 3 [2, 3, 4, 5, 3, 3, 1, 80, 3] should be 4
This is my code
howManyTimes y [] = 0
howManyTimes y xs = howManyIntern y (x:xs) acc
| x == y = howManyIntern y xs (acc + 1)
| otherwise = howManyIntern y xs acc
And I receive this error message. Variable not in scope: howManyTimes :: Integer -> [Integer] -> t
Can anyone say me a hint?
I have rewrite my code. I do not receive an error any more but output is 0
howManyTimes y xs = howManyIntern y xs 0
where howManyIntern y [] acc = 0
howManyIntern y (x:xs) acc | x == y = howManyIntern y xs (acc + 1)
| otherwise = howManyIntern y xs acc
The output is 0 from above code in comment since the expression:
howManyIntern y [] acc = 0
return 0 whenever it finish the counting. It is easy to be fixed by return acc instead:
howManyIntern y [] acc = acc
An alternative way to do that uses existing functions:
howManyTimes y xs = length $ filter (==y) xs
I'm expecting luhn 5594589764218858 = True but it is always False
-- Get the last digit from a number
lastDigit :: Integer -> Integer
lastDigit 0 = 0
lastDigit n = mod n 10
-- Drop the last digit from a number
dropLastDigit :: Integer -> Integer
dropLastDigit n = div n 10
toRevDigits :: Integer -> [Integer]
toRevDigits n
| n <= 0 = []
| otherwise = lastDigit n : toRevDigits (dropLastDigit n)
-- Double every second number in a list starting on the left.
doubleEveryOther :: [Integer] -> [Integer]
doubleEveryOther [] = []
doubleEveryOther (x : []) = [x]
doubleEveryOther (x : y : z) = x : (y * 2) : doubleEveryOther z
-- Calculate the sum of all the digits in every Integer.
sumDigits :: [Integer] -> Integer
sumDigits [] = 0
sumDigits (x : []) = x
sumDigits (x : y) = (lastDigit x) + (dropLastDigit x) + sumDigits y
-- Validate a credit card number using the above functions.
luhn :: Integer -> Bool
luhn n
| sumDigits (doubleEveryOther (toRevDigits n)) `div` 10 == 0 = True
| otherwise = False
I know it can be done easier but I'm following a Haskell introductory. I think my only problem is in the luhn function. The course mentions problems may occur because toRevDigits reverses the number but I think it should work anyways.
The snippet x `div` 10 == 0 is not a correct check that x is divisible by ten; you should use `mod` instead. Also, this equation is incorrect:
sumDigits (x : []) = x
(Try, e.g. sumDigits [10].) It can be fixed, but deleting it is simpler and still correct.
I want to write a function wp (without primes) which removes all the primes from a list
of numbers. Thus, wp [1, 2, 3, 4, 5, 6, 7] = [1, 4, 6].
I tried coding it like this:
wp :: [Int] -> [Int]
prime :: Int -> Bool
prime n = if f n > 0 then False else True
where f n = foldl (\acc x -> if n `mod` x == 0 then acc = acc + 1 else acc = acc + 0) 0 [2..n-1]
wp xs = filter (not.prime) xs
But when compiling it, I get the "parse error on input =" error but I can't find my syntax error. Any ideas?
Your problem is in the use of acc = acc + x. You just need to write it as acc + 1 or acc + 0 (or just acc really) instead. Also, I would recommend writing the function signature on top of the function definition, rather than a C-style list at the top.
Finally, I should note that wp will not include 1 in the result, so you will have to manually include it.
prime :: Int -> Bool
prime n = if f n > 0 then False else True
where f n = foldl (\acc x -> if n `mod` x == 0 then acc + 1 else acc) 0 [2..n-1]
wp :: [Int] -> [Int]
wp xs = 1 : filter (not.prime) xs
I was trying to define a function(s) that helped me simulate basic operations when using 8-Bit numbers.
I'm having a hard time figuring this one out.. I'm trying to keep it as simple as possible without importing anything, so I started with two lists of 8 elements in it (which are 0's and 1's).
If I'm not mistaken it should start looking like this:
bitsum :: [Int] -> [Int] -> [Int]
bitsum [][] = []
after this last line it starts to get kind of tricky for me because I can't add one to one the elements the lists.
bitsum (x:xs)(y:ys)
that's all that I have right now that I think is correct.
My idea was to try something like this:
bitsum :: [Int] -> [Int] -> [Int]
bitsum [][] = []
bitsum (x:xs)[] = (x:xs)
bitsum [](y:ys) = (y:ys)
bitsum (x:xs)(y:ys) | (x:xs) == (y:ys) && < 0 = (x:xs)
| (x:xs) == (y:ys) && > 0 =
but I think I'm taking a wrong turn somewhere.
I would really appreciate if someone could give me a hand with this problem.
You are going to need a carry bit. You can't add column by column. Let's do it piece by piece:
bitsum :: [Int] -> [Int] -> [Int]
bitsum = bitsum' 0
where
bitsum' _ [] [] = []
There's a start. We start with no carry, and we deal with the case of no more bits to add. So what if both bits are 0?
bitsum' 0 (0:xs) (0:ys) = 0 : bitsum' 0 xs ys
bitsum' 1 (0:xs) (0:ys) = 1 : bitsum' 0 xs ys
Okay, so if both are 0, and carry is 0, then the result for that bit is 0 and no carry. If there is a carry use it, and continue without one.
bitsum' 0 (1:xs) (1:ys) = 0 : bitsum' 1 xs ys
bitsum' 1 (1:xs) (1:ys) = 1 : bitsum' 1 xs ys
If they are one, its similar. except there will always be a carry. And then if they are different:
bitsum' 0 (x:xs) (y:ys) = 1 : bitsum' 0 xs ys
bitsum' 1 (x:xs) (y:ys) = 0 : bitsum' 1 xs ys
Well they have to be 0 and 1 because we've dealt with all other cases, so they must add up to one. You can figure out what it should be from that. You start to see some patterns above, and so this can all be condensed to end up with a shorter answer.
bitsum :: [Int] -> [Int] -> [Int]
bitsum = bitsum' 0
where
bitsum' _ [] [] = []
bitsum' carry (x:xs) (y:ys) | x == y = carry : bitsum' x xs ys
| otherwise = (1 - carry) : bitsum' carry xs ys
(1-carry) is a fancy way of flipping a 1 to 0 or vice versa since in that case the bit is always the opposite of the carry.
Carries are unnecessary for this. Note two properties of bitwise binary addition: the high digit is given by AND and the low digit is given by XOR. These are:
xor a b = if a == b then 0 else 1
and' 1 1 = 1 -- `and` is a function in Prelude.
and' _ _ = 0
To find the binary sum, simply take the bitwise xor and and to find the low and high digits, respectively. Shift the high digits (left or right, depending on Endian-ness) and take the sum of that, and the low digits.
Little endian:
bitsum0 :: [Int] -> [Int] -> [Int]
bitsum0 xs ys
| (sum xs) == 0 = ys
| (sum ys) == 0 = xs
| otherwise = bitsum0 low (0:high)
where low = zipWith xor xs ys
high = zipWith and' xs ys
Big endian:
bitsum1 :: [Int] -> [Int] -> [Int]
bitsum1 xs ys
| (sum xs) == 0 = ys
| (sum ys) == 0 = xs
| otherwise = bitsum1 low ((tail high) ++ [0])
where low = zipWith xor xs ys
high = zipWith and' xs ys
The two guards in each function ensure termination ; eventually, the recursion will end up adding x+0, which is when we are finished.
Note that no error checking is done. Overflows and lists of different lengths (as well as null lists) are undefined behaviour. Your lists could be filled full of meaningless garbage (particulary, and' treats 0 as 0 and everything else as 1). Perhaps it would be more pragmatic to use something like
data Bit = Bool
type Word_8 = (Bit , Bit , Bit , Bit , Bit , Bit , Bit , Bit )
or better yet
import Data.Word
binsum :: Word8 -> Word8 -> Word8
binsum = (+)
This is a super simple gate representation in Haskell.
Just began learning Haskell so the format is simple and how I'm learning..
Since building a bit sim in maths seemed fun, I hacked this together.. Hope it helps someone :)
andGate x y = [z | z <- [if (x == 1 && y == 1) then 1 else 0]]
orGate x y = [z | z <- [if (x == 1 || y == 1) then 1 else 0]]
nandGate x y = [z | q <- (andGate x y), z <- [if (q == 0) then 1 else 0 ]]
norGate x y = [z | q <- (orGate x y), z <- [if (q == 0) then 1 else 0 ]]
xorGate x y = [z |
xn <- [if (x == 0) then 1 else 0],
yn <- [if (y == 0) then 1 else 0],
q <- (andGate xn y),
p <- (andGate x yn),
z <- (orGate q p)]
xnorGate x y = [z |
xn <- [if (x == 0) then 1 else 0],
yn <- [if (y == 0) then 1 else 0],
q <- (andGate xn yn),
p <- (andGate x y),
z <- (orGate q p)]
halfAdder a b = [ (x, y) | x <- (xorGate a b), y <- (andGate a b)]
fullAdder a b c = [ (sum, cout) |
u1 <- xorGate a b,
u2 <- andGate a b,
sum <- xorGate u1 c,
u4 <- andGate u1 c,
cout <- orGate u4 u2]