Convert binary string to integer value using first order functions - haskell

Given a finite list of 0 and 1, how can I convert them to their integer value using first order function?
The head of the list is the least significant digit. For instance, 1011 evaluates to 13.
In this problem, I struggle to find both the recursive step and the base step because all depends wether it's a 0 and 1.
EDIT :
The goal is to define a function that will compute the decimal value given a binary string. An empty list should return 0 I guess, so it would be the base case.

Wrapping up my comments:
convert :: [Int] -> Int
convert [] = 0
convert (x : xs) = x + 2 * convert xs
The base case is the empty list, returning 0.
The recursive case follows from the fact that x is the least significant digit. convert xs (the recursive call) gives us the result for the tail of the list; to get the result of the whole list we need to multiply by 2 (to "shift over" the digits) and add x (0 or 1).

Here's my initial thoughts about how to handle this situation.
import Data.Char (digitToInt)
myFunction :: String -> Int
myFunction = foldr step 0
where step x y = (+) (digitToInt x) ( (*) y 2 )

Assuming the input is a list of 1s and 0s.
bin2num :: [Int] -> Int
bin2num list = go list 0
where go [] _ = 0
go (x:xs) n = (x*(2^n)) + (go xs (n+1))

Just double the acc and add it to the new element of the list . Easily use digitToInt to get the right list from the string _ st here . and foldl' for efficiency. This is Sanaz's answer
fromBin st = foldl' (\x acc -> x * 2 + acc ) 0 (map (digitToInt) st)

Related

Adding two functions together in Haskell

Hi I am new in Haskell and I came across an interesting problem but I was not really sure on how I would go about solving it. I am about to show you only two parts of the question as an example.
The question is that we are to input a number between 13 to 15 digits.
then from that number we remove the last number. such as 19283828382133 should out put the exact same number just without the final 3, 1928382838213.
Then every odd digit(not number) from these numbers will be doubled. So you will get 2,9,4,8,6 etc
This is my code so far. As you can see from the code I have been able to complete these two parts individually(working) but I am not sure how I would add them together.
lastdigit :: Integer -> Integer -- This Function removes the last number
lastdigit x = x`div`10
doubleOdd (x:xs) = (2*x):(doubleEven xs) -- This function doubles every odd digit not number.
doubleOdd [] = []
doubleEven (x:xs) = x:(doubleOdd xs)
doubleEven [] = []
So to further explain the program I am trying to build will first go through the step of taking in the number between 13 to 15 digits. Then it will first remove the last number then automatically go to the next step of doubling each odd digit(not number). Thanks
First, you need a way to break some large number into digits.
digits :: Integral x => x -> [x]
digits 0 = []
digits x = digits (x `div` 10) ++ [x `mod` 10]
Which gives you...
Prelude> digits 12345
[1,2,3,4,5]
You can then drop the last digit with init
Prelude> (init . digits) 12345
[1,2,3,4]
The a helper function to map over odd elements in a list.
mapOdd _ [] = []
mapOdd f (x:[]) = [f x]
mapOdd f (x:y:rest) = f x : y : mapOdd f rest
Giving you...
Prelude> mapOdd (+10) [1..10]
[11,2,13,4,15,6,17,8,19,10]
And a function to get back to a large number...
undigits = sum . zipWith (*) [10^n | n <- [0..]] . reverse
Resulting in...
Prelude> undigits [1, 2, 3, 4]
1234
And putting it all together
Prelude> undigits . mapOdd (*2) . init . digits $ 12345
2264
In functional languages particularly, always try to solve a problem by composing solutions to smaller problems :)
The missing component is a way to break down an integer into its digits, and build it back up from there. That's easy:
digits:: Int -> [Int]
digits = map (`mod` 10) . takeWhile (/= 0) . iterate (`div` 10)
undigits :: [Int] -> Int
undigits = foldr f 0 where f i r = 10 * r + i
Then it looks like you need to post-process those digits in two different ways, but only if they match a predicate. Let's build a combinator for that:
when :: (a -> Bool) -> (a -> a) -> a -> a
when p f a = if p a then f a else a
The first case appears when you want to double digits in odd position (from left to right). Again trivial, with the minor inconvenience that digits breaks down a number by increasing power of ten. Let's prefix each number by its position:
prefix :: [Int] -> [(Int, Int)]
prefix is = let n = length is in zip [n, n-1..1] is
doubleOdd can now be expressed as
doubleodd :: [Int] -> [Int]
doubleodd = map (snd . when (odd . fst) (id *** double)) . prefix
You mentioned in a comment that when the double number overflows, its digits must be added together. This is the second case I was referring to and is again simplicity itself:
double :: Int -> Int
double = when (>= 10) (sum . digits) . (* 2)
Here is your final program:
program = undigits . doubleodd . tail . digits
... assuming the "between 13 and 15 digits" part is verified separately.
I hope this helps and realize it could be cleaned up a lot. List indices start with 0 which is also an even number and the first element of a list. The list comprehension processes 0,2,4 ... the 1st,2nd and 3rd items.
let f n = [mod n 10] ++ f (div n 10)
let r = [if even i then d*2 else d|(i,d)<-zip [0..] (init.reverse.take 14.f$19283828382133)]
sum [b*(10^a)|(a,b) <- zip [12,11..0] r]
2948684868416
If you want it to handle any length number, the easiest way here is length $ show 19283828382133 but I do have a function somewhere that does that. Use the length as a value in 3 places, once at full value in thetake function in the composition.

How to break a number into a list of digits? [duplicate]

Given an arbitrary number, how can I process each digit of the number individually?
Edit
I've added a basic example of the kind of thing Foo might do.
For example, in C# I might do something like this:
static void Main(string[] args)
{
int number = 1234567890;
string numberAsString = number.ToString();
foreach(char x in numberAsString)
{
string y = x.ToString();
int z = int.Parse(y);
Foo(z);
}
}
void Foo(int n)
{
Console.WriteLine(n*n);
}
Have you heard of div and mod?
You'll probably want to reverse the list of numbers if you want to treat the most significant digit first. Converting the number into a string is an impaired way of doing things.
135 `div` 10 = 13
135 `mod` 10 = 5
Generalize into a function:
digs :: Integral x => x -> [x]
digs 0 = []
digs x = digs (x `div` 10) ++ [x `mod` 10]
Or in reverse:
digs :: Integral x => x -> [x]
digs 0 = []
digs x = x `mod` 10 : digs (x `div` 10)
This treats 0 as having no digits. A simple wrapper function can deal with that special case if you want to.
Note that this solution does not work for negative numbers (the input x must be integral, i.e. a whole number).
digits :: Integer -> [Int]
digits = map (read . (:[])) . show
or you can return it into []:
digits :: Integer -> [Int]
digits = map (read . return) . show
or, with Data.Char.digitToInt:
digits :: Integer -> [Int]
digits = map digitToInt . show
the same as Daniel's really, but point free and uses Int, because a digit shouldn't really exceed maxBound :: Int.
Using the same technique used in your post, you can do:
digits :: Integer -> [Int]
digits n = map (\x -> read [x] :: Int) (show n)
See it in action:
Prelude> digits 123
[1,2,3]
Does that help?
You could also just reuse digits from Hackage.
Textbook unfold
import qualified Data.List as L
digits = reverse . L.unfoldr (\x -> if x == 0 then Nothing else Just (mod x 10, div x 10))
You can use
digits = map (`mod` 10) . reverse . takeWhile (> 0) . iterate (`div` 10)
or for reverse order
rev_digits = map (`mod` 10) . takeWhile (> 0) . iterate (`div` 10)
The iterate part generates an infinite list dividing the argument in every step by 10, so 12345 becomes [12345,1234,123,12,1,0,0..]. The takeWhile part takes only the interesting non-null part of the list. Then we reverse (if we want to) and take the last digit of each number of the list.
I used point-free style here, so you can imagine an invisible argument n on both sides of the "equation". However, if you want to write it that way, you have to substitute the top level . by $:
digits n = map(`mod` 10) $ reverse $ takeWhile (> 0) $ iterate (`div`10) n
Via list comprehension:
import Data.Char
digits :: Integer -> [Integer]
digits n = [toInteger (digitToInt x) | x <- show n]
output:
> digits 1234567890
[1,2,3,4,5,6,7,8,9,0]
I was lazy to write my custom function so I googled it and tbh I was surprised that none of the answers on this website provided a really good solution – high performance and type safe. So here it is, maybe somebody would like to use it. Basically:
It is type safe - it returns a type checked non-empty list of Word8 digits (all the above solutions return a list of numbers, but it cannot happen that we get [] right?)
This one is performance optimized with tail call optimization, fast concatenation and no need to do any reversing of the final values.
It uses special assignment syntax which in connection to -XStrict allows Haskell to fully do strictness analysis and optimize the inner loop.
Enjoy:
{-# LANGUAGE Strict #-}
digits :: Integral a => a -> NonEmpty Word8
digits = go [] where
go s x = loop (head :| s) tail where
head = fromIntegral (x `mod` 10)
tail = x `div` 10
loop s#(r :| rs) = \case
0 -> s
x -> go (r : rs) x
Here's an improvement on an answer above. This avoids the extra 0 at the beginning ( Examples: [0,1,0] for 10, [0,1] for 1 ). Use pattern matching to handle cases where x < 10 differently:
toDigits :: Integer -> [Integer] -- 12 -> [1,2], 0 -> [0], 10 -> [1,0]
toDigits x
| x < 10 = [x]
| otherwise = toDigits (div x 10) ++ [mod x 10]
I would have put this in a reply to that answer, but I don't have the needed reputation points :(
Applicative. Pointfree. Origami. Neat.
Enjoy:
import Data.List
import Data.Tuple
import Data.Bool
import Control.Applicative
digits = unfoldr $ liftA2 (bool Nothing) (Just . swap . (`divMod` 10)) (> 0)
I've been following next steps(based on this comment):
Convert the integer to a string.
Iterate over the string
character-by-character.
Convert each character back to an integer,
while appending it to the end of a list.
toDigits :: Integer -> [Integer]
toDigits a = [(read([m])::Integer) | m<-show(a)]
main = print(toDigits(1234))
For returning a list of [Integer]
import Data.Char
toDigits :: Integer -> [Integer]
toDigits n = map (\x -> toInteger (digitToInt x)) (show n)
The accepted answer is great but fails in cases of negative numbers since mod (-1) 10 evaluates to 9. If you would like this to handle negative numbers properly... which may not be the case the following code will allow for it.
digs :: Int -> [Int]
digs 0 = []
digs x
| x < 0 = digs ((-1) * x)
| x > 0 = digs (div x 10) ++ [mod x 10]
The accepted answer is correct except that it will output an empty list when input is 0, however I believe the output should be [0] when input is zero.
And I don't think it deal with the case when the input is negative. Below is my implementation, which solves the above two problems.
toDigits :: Integer -> [Integer]
toDigits n
| n >=0 && n < 10 = [n]
| n >= 10 = toDigits (n`div`10) ++ [n`mod`10]
| otherwise = error "make sure your input is greater than 0"
I would like to improve upon the answer of Dave Clarke in this page. It boils down to using div and mod on a number and adding their results to a list, only this time it won't appear reversed, nor resort to ++ (which is slower concatenation).
toDigits :: Integer -> [Integer]
toDigits n
| n <= 0 = []
| otherwise = numToDigits (n `mod` 10) (n `div` 10) []
where
numToDigits a 0 l = (a:l)
numToDigits a b l = numToDigits (b `mod` 10) (b `div` 10) (a:l)
This program was a solution to a problem in the CIS 194 course at UPenn that is available right here. You divide the number to find its result as an integer and the remainder as another. You pass them to a function whose third argument is an empty list. The remainder will be added to the list in case the result of division is 0. The function will be called again in case it's another number. The remainders will add in order until the end.
Note: this is for numbers, which means that zeros to the left won't count, and it will allow you to have their digits for further manipulation.
digits = reverse . unfoldr go
where go = uncurry (*>) . (&&&) (guard . (>0)) (Just . swap . (`quotRem` 10))
I tried to keep using tail recursion
toDigits :: Integer -> [Integer]
toDigits x = reverse $ toDigitsRev x
toDigitsRev :: Integer -> [Integer]
toDigitsRev x
| x <= 0 = []
| otherwise = x `rem` 10 : toDigitsRev (x `quot` 10)

Using fold* to grow a list in Haskell

I'm trying to solve the following problem in Haskell: given an integer return the list of its digits. The constraint is I have to only use one of the fold* functions (* = {r,l,1,l1}).
Without such constraint, the code is simple:
list_digits :: Int -> [Int]
list_digits 0 = []
list_digits n = list_digits r ++ [n-10*r]
where
r = div n 10
But how do I use fold* to, essentially grow a list of digits from an empty list?
Thanks in advance.
Is this a homework assignment? It's pretty strange for the assignment to require you to use foldr, because this is a natural use for unfoldr, not foldr. unfoldr :: (b -> Maybe (a, b)) -> b -> [a] builds a list, whereas foldr :: (a -> b -> b) -> b -> [a] -> b consumes a list. An implementation of this function using foldr would be horribly contorted.
listDigits :: Int -> [Int]
listDigits = unfoldr digRem
where digRem x
| x <= 0 = Nothing
| otherwise = Just (x `mod` 10, x `div` 10)
In the language of imperative programming, this is basically a while loop. Each iteration of the loop appends x `mod` 10 to the output list and passes x `div` 10 to the next iteration. In, say, Python, this'd be written as
def list_digits(x):
output = []
while x > 0:
output.append(x % 10)
x = x // 10
return output
But unfoldr allows us to express the loop at a much higher level. unfoldr captures the pattern of "building a list one item at a time" and makes it explicit. You don't have to think through the sequential behaviour of the loop and realise that the list is being built one element at a time, as you do with the Python code; you just have to know what unfoldr does. Granted, programming with folds and unfolds takes a little getting used to, but it's worth it for the greater expressiveness.
If your assignment is marked by machine and it really does require you to type the word foldr into your program text, (you should ask your teacher why they did that and) you can play a sneaky trick with the following "id[]-as-foldr" function:
obfuscatedId = foldr (:) []
listDigits = obfuscatedId . unfoldr digRem
Though unfoldr is probably what the assignment meant, you can write this using foldr if you use foldr as a hylomorphism, that is, building up one list while it tears another down.
digits :: Int -> [Int]
digits n = snd $ foldr go (n, []) places where
places = replicate num_digits ()
num_digits | n > 0 = 1 + floor (logBase 10 $ fromIntegral n)
| otherwise = 0
go () (n, ds) = let (q,r) = n `quotRem` 10 in (q, r : ds)
Effectively, what we're doing here is using foldr as "map-with-state". We know ahead of time
how many digits we need to output (using log10) just not what those digits are, so we use
unit (()) values as stand-ins for those digits.
If your teacher's a stickler for just having a foldr at the top-level, you can get
away with making go partial:
digits' :: Int -> [Int]
digits' n = foldr go [n] places where
places = replicate num_digits ()
num_digits | n > 0 = floor (logBase 10 $ fromIntegral n)
| otherwise = 0
go () (n:ds) = let (q,r) = n `quotRem` 10 in (q:r:ds)
This has slightly different behaviour on non-positive numbers:
>>> digits 1234567890
[1,2,3,4,5,6,7,8,9,0]
>>> digits' 1234567890
[1,2,3,4,5,6,7,8,9,0]
>>> digits 0
[]
>>> digits' 0
[0]
>>> digits (negate 1234567890)
[]
>>> digits' (negate 1234567890)
[-1234567890]

Attempting to convert ints into strings in haskell

I am attempting to write a code to take in an integer and output that integer in words. Ex: if the input is 4321 the output is four thousand three hundred twenty one.
For this, I would first like to break the input into it's individual digits. ex input 4321 would become an array of [4,3,2,1].
My current code
newtype wordInt = WI Int
instance Show WordInt where
show (WI x) | x>= 0 = helper x
| x < 0 = helper -x
helper 0 = [0]
helper x = x `mod` 10 : helper (x `div` 10)
At the moment, I think i'm getting a type error.
Please note that this needs to be able to hand both positive and negative numbers. Also, if you can think of an efficient way to do the conversion i'm looking for, it would be much appreciated.
Names of types cannot begin with a lowercase letter. Change wordInt to WordInt here:
newtype wordInt = WI Int
The method show of the Show class must return a String and your helper has the type Int -> [Int] (when applied to an Int). You need to somehow convert the list into a String, for instance by calling show on the list:
instance Show WordInt where
show (WI x) | x >= 0 = show $ helper x
| x < 0 = show $ helper (-x)
Finally, notice that I put -x in parentheses. This is needed for unary minus because otherwise the compiler will think you are trying to subtract x from helper (which is a function and not an Int).
However, your implementation of helper is wrong because it returns the list of digits in reverse. To fix this, you can write a helper function to split the digits and then reverse the list:
helper :: Int -> [Int]
helper = reverse . go
where go 0 = [0]
go x = x `mod` 10 : go (x `div` 10)
However, this will pad the number with a leading zero:
λ. helper 4321
[0,4,3,2,1]
This doesn't change the meaning, of course, but if it is a problem, write a wrapper function to deal with this case:
helper :: Int -> [Int]
helper x =
case splitIntoDigits x of
[] -> [0]
xs -> reverse xs
splitIntoDigits :: Int -> [Int]
splitIntoDigits 0 = []
splitIntoDigits x = x `mod` 10 : splitIntoDigits (x `div` 10)
It then works in both cases:
λ. helper 0
[0]
λ. helper 4321
[4,3,2,1]

Check an array whether sum(x_0, x_1...x_k) == sum(x_k+1,..x_n) are equal in Haskell

I need to implement to an algorithm to solve following problem in Haskell:
Given an array, check whether sum(x_0, x_1...x_k) == sum(x_k+1,...,x_n)
If the array is have NO element, then the sum is zero
1:
arr = [1]
sum([]) = 0
sum([1]) = 1
sum([]) != sum([1])
there is no such k
return False
2:
arr = [1,2,3]
sum([1,2]) == sum([3])
there is such k
return True
Here is my current implementation so far:
checkSum::[Int]->Int->Bool
checkSum [] _ = True
checkSum [x] _ = x == 0
checkSum l inx | sum(take inx l) == sum(drop inx l) = True
| inx <= length l = checkSum l (inx+1)
| otherwise = False
It works, but I need to change function prototype as following:
checkSum::[Int]->Bool
.....
Does anyone know how to implement the new function without passing index to the function?
This function comes up a surprising amount:
import Data.List (inits, tails)
splits :: [a] -> [([a],[a])]
splits xs = zip (inits xs) (tails xs)
Example usage:
ghci> splits [1,2,3]
[([],[1,2,3]),([1],[2,3]),([1,2],[3]),([1,2,3],[])]
You might also be interested in the any function.
I think you can take it from here.
A more primitive approach
checkSum :: [Int] -> Bool
checkSum a = go a 0 (sum a)
where go [] left right = left==right
go (x:xs) left right = left==right || go xs (left+x) (right-x)
at each step you're adding the element to the left value and subtracting from the right, where the initial values are 0 and sum. Terminates when equality reached at any step or when the array is exhausted.
A clever way to think about this: if we need
x[1] + ... + x[k] == x[k+1] + ... + x[n],
then we can add the left-hand side to both sides to get
(x[1] + ... + x[k]) * 2 == sum(x).
Thus, we can generate all doubled prefix sums, then look for sum(x) in them.
checkSum :: [Int] -> Bool
checkSum xs = sum xs `elem` doublePrefixSums
where doublePrefixSums = scanl (\acc x -> acc + 2*x) 0 xs
A solution using built-in functions.
Use scanl and scanr to find all the sums from the left and right.
scanl (+) 0 [1,2,3] gives you [0, 0+1, 0+1+2, 0+1+2+3]
λ> scanl (+) 0 [1,2,3]
[0,1,3,6]
scanr (+) 0 [1,2,3] gives you [1+2+3+0, 2+3+0, 3+0, 0]
λ> scanr (+) 0 [1,2,3]
[6,5,3,0]
Then zipWith to identify positions where the lists have equal elements.
λ> zipWith (==) [0,1,3,6] [6,5,3,0]
[False,False,True,False]
Then or to check if this list contains True anywhere.
λ> or [False,False,True,False]
True
The complete function:
checkSum :: [Int] -> Bool
checkSum xs = or (zipWith (==) leftSums rightSums)
where
leftSums = scanl (+) 0 xs
rightSums = scanr (+) 0 xs
(This will return True on the empty list. This seems reasonable to
me, but if you want it to be False you could write a special case for
it or just change scanr to scanr1.)
My interpretation of the question is: for some Int list x, determine ∃k::Integer. sum[x₀,…,xₖ] == sum[xₖ,…,xₙ]. Reasonably, 0 ≤ k < length x (and n = length x) because otherwise xₖ is ⊥ and we are not interested in that case.
So how would you prove that proposition? Are we interested in infinite lists? Probably not, so let us assume the list is finite. Then, if the list is finite there are also finite choices for k because 0 ≤ k < length x. A proof then can be done by checking for every choice of k. If at least one choice of k satisfies the proposition then it is true, and otherwise it is false.
When translating our method to Haskell we want to leverage existing definitions to their fullest. We can just focus on the splits of the list itself, leaving k out of the implementation. luqui's answer beautifully demonstrates this. Be aware that an abstract notation (mathematical, logical, a specification, etc) does not always indicate a good implementation.
Once we know all the splits of the list, we can sum and compare for equality. If at least one comparison succeeds then yield True, otherwise yield False.

Resources