I need to convert a string of chars to a list of binary numbers in Haskell. I've written two functions to do this, but I'm not sure how to combine them into one. So far I have
dec[]=[]
dec(x:xs) = ord(x): dec xs
to convert every char in the list into a decimal number. The next function
bin 0 = [0]
bin n| n `mod` 2 == 1 = bin (n `div` 2) ++ [1]
| n `mod` 2 == 0 = bin (n `div` 2) ++ [0]
converts a decimal number to its binary equivalent. I'm not sure how to apply the second function to every element in the list, in order to convert every char to its equivalent in binary. I tried to use the where clause:
where n = dec(x:xs) = ord(x): dec xs
but this is not valid as there are two equals signs on the same line. How can I achieve the correct functionality?
You can be pretty certain that an Int will be stored in binary. It only appears to be in decimal because it is converted to decimal when you print it. So, the name dec is a misnomer, that function is converting a String into a sequence of numbers that represent the Unicode value of each character. You can avoid explicit recursion by using map:
toUnicode :: String -> [Int]
toUnicode = map ord
Note that this function uses so-called point-free style. The expected argument is missing, but will be passed to map when supplied by the caller.
The Bin function will not compile because it starts with an upper case character, making it a data constructor. You should name the function starting with a lower case character. According to your example output, you want leading zeros in your binary representations, so you can't stop conversion when the value becomes zero. You need to continue until you have converted the desired number of digits, which appears to be 8. It is also inefficient to keep appending to a list. It is better to prepend, and then reverse the result.
toBinary :: Int -> [Int]
toBinary = go 8 [] where
go 0 acc _ = reverse acc
go n acc x = go (n-1) (bit:acc) x' where
(x', bit) = x `divMod` 2
Here, we use a helper function, go which counts down the number of remaining digits as it builds up the list of 1's and 0's.
So, now we have a function to convert a String into a list of Ints, and a function to convert an Int into a list of 0/1 Ints, and we want to glue them together to make a function that converts a String to a list of 0/1 Ints. If we map our toBinary function over the result of toUnicode, we will get a list of lists, which must be concatenated to form a single list. This is such a common pattern that there's a function for that called, concatMap:
stringToBinary :: String -> [Int]
stringToBinary = concatMap toBinary . toUnicode
Here we use function composition to first apply toUnicode to the String, and then concatMap the toBinary over the result.
What we want is a function of type String -> String (decimal -> binary). What you have now is
dec :: String -> [Int]
bin :: Int -> [Int] -- use *lowercase*
So it seems impossible to compose a function of type String -> String only with these two. Besides, ord is not what you want.
*Main> dec "123"
[49,50,51]
*Main> bin 123
[0,1,1,1,1,0,1,1]
From what you have now, the possible solution would be:
*Main Data.Char> toBinary = map intToDigit . bin . read
*Main Data.Char> toBinary "123"
"01111011"
I guess your intention may be dec :: String -> Int, then bin . dec :: String -> [Int]. You can follow the type signature and retry.
Related
I need to sum the elements from a 2D list of three- tuples of Ints
E.g[(10,50,50),(60,70,90),(100,100,20)],](50,60,100),(60,70,90),(60,40,30)]
and divide it by 3 and then 255.
right now I have this
PatternMatch:: [Char] -> Bool -> (Int, Int, Int)-> Char
PatternMatch _ _[] = []
PatternMatch ((a,b,c):xs) = (((a + b + c) / 3) / 255) : (PatternMatch xs)
But this returns it as an integer, but I need a char. For that I need a helper function, but idk how to go about this. Please help!
Hoogle and google can easily help you with this question. You are just looking for a function of type Int -> String (char would be restricted to only one digit; also watch out for decimal values). You'll find that the well-known function Show does what you need.
Also, dividing by 3 and 255 makes your code look weird, just divide by 765 at once.
Finally, there's no need for pattern matching for a function like this, you can use the higher order function map :: (a -> b) -> [a] -> [b] and either write your own helper function or use a lambda function:
patternMatch :: [(Int,Int,Int)] -> String
patternMatch = concat . map (show . (\(x,y,z) -> (x+y+z) `div` 765))
P.S.: If you are sure you'll only get integers 0..9, then you can use an even simpler list comprehension:
patternMatch tups = [head . show $ (x+y+z) `div` 765 |(x,y,z) <- tups]
I'm trying to create a function that concatenates parts of strings in a list to another. I already know how to select the strings I want but now I need the first part of them (and it's not always the same value).
So I want to cut the first part of a string
-- here is a function that should take a string and the numbers
-- of characters we want to take from the start
cutString :: Int -> String -> String
cutString x str = cut x str -- here's a way to take the first x characters
And the way to use it:
print (cutString 3 "Hello World")
Output --> "Hel"
Is there any simple ways to do that?
Thanks for any help or advices.
See take:
take :: Int -> [a] -> [a]
take n, applied to a list xs, returns the prefix of xs of length n, or xs itself if n > length xs
Using it in Prelude shows:
Prelude> take 3 "Hello"
"Hel"
You can implement take yourself with explicit recursion:
-- note the signature here is less general than it need be:
-- cutString :: Int -> [a] -> [a]
cutString :: Int -> String -> String
cutString 0 _ = []
cutString n (x:xs)
| n > 0 = x : cutString (n-1) xs
| otherwise = []
cutString _ _ = []
The first alternation is your usual base case -- taking zero elements of anything is the empty string: [].
The second alternation is your recursive case. If n is zero, execution hits the first alternation, so we only have to worry about two cases here: either n is greater than zero in which case we give back one character and recurse with n-1, or n is less than zero in which case we catch the edge case and give back something sensible. Taking less than zero elements from a string isn't a sensible thing to do, so you could choose your response here -- error might be appropriate.
The third alternation is the fallback and is another base case. If n is still not zero, but we've run out of items in the string, stop recursing and give back []. Without this case, the code crashes on cutString 100 "Hello" (anything where n > length str)
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)
I was doing some Haskell exercises but can't solve the last one.
I need to recursively define functions that are already defined in the Data.Char module.
The last function I need to define is of this type:
nums :: String -> [Int]
Here is the (translated) question:
Using functions from the Data.Char module, define recursively the following functions:
(c) nums :: String -> [Int] which receives a string and outputs a list
with the algarisms that occur on that string, by the same order.
--This is my code
numbers :: String -> [Int]
numbers [] = []
numbers (l:ls) = if ord l >= 48 && ord l <= 57
then l : (numbers ls)
else (numbers ls)
I've been getting this error on the interpreter:
pratica3.hs:137:14:
Couldn't match expected type `Int' with actual type `Char'
In the first argument of `(:)', namely `l'
In the expression: l : (numbers ls)
In the expression:
if ord l >= 48 && ord l <= 57 then
l : (numbers ls)
else
(numbers ls)
Failed, modules loaded: none.
Thank you.
Since this is a class problem, here are some hints. Use the function words to first break the string into individual elements, drop all non-numeric characters, then read "elem":Int for each element of your string and filter out those that return false. What's left will be [Int].
The magic as is obvious is in the read function that takes a char representation of numbers and converts them to Int. If you have very large numbers, consider using read "elem":Integer variation.
Ok,
The solution is:
numbers :: String -> [Int]
numbers [] = []
numbers (l:ls) = if ord l >= 48 && ord l <= 57
then (ord l - 48): (numbers ls)
else (numbers ls)
This solves my problem, which is (and now I'll try to explain it better):
Using functions from the Data.Char module, define recursively the
following functions:
(c) nums :: String -> [Int] which receives a string and outputs a list
with the algarisms that occur on that string, by the same order.
Please keep in mind that this was made for students that had less than 8 hours of contact with the haskell language and 0 with any other language.
If this is incorrect, I would appreciate any answer. I want to learn.
Note: this solution doesn't seem to be the most complete. Alas, it is made for students that just started learning Haskell and don't know how to use the words and map functions.
I currently have the Haskell function below which converts an integer into a list of digits taken from the original integer. My question is thus: Is there a way to do this without using mod and div? For example, if I wanted to do the same thing with a string I could create a function utilising other functions such as head and tail etc.
I struggled with this problem for a while before finally come to SO and finding the answer in another post. What got me asking this question is the fact that I would have never thought of using mod and div myself!
toDigits :: Integer -> [Integer]
toDigits n
| n < 1 = []
| otherwise = toDigits (n `div` 10) ++ [n `mod` 10]
You mentioned that you could do the same thing on strings with list operations. Indeed, that would be another way. You could convert the integer to a string and then convert each character to an integer:
import Data.Char (digitToInt)
toDigits :: Int -> [Int]
toDigits = map digitToInt . show
Here I used Int rather than Integer, but you can use Integer if you really want with a little more trouble:
toDigits :: Integer -> [Integer]
toDigits = map (fromIntegral . digitToInt) . show
#icktoofay's answer uses show, a generic way to convert some value to a String (in other words, get its string representation). A value should be of a type that is an instance of a typeclass Show. For example, Int is an instance of Show (enter :i Int in ghci and seek for a string instance Show Int -- Defined in `GHC.Show'). But a function isn't an instance of Show, so let f n = n in f will throw an error, because how would you convert a function to a string? (See also: If functions as instances of the Show typeclass). Anyway, using show function is idiomatic, so you can stick to it.
There is however a way to extract a digit from a number using logarithms, powers and integer divisions. Remember that you can remove digits from the left by finding a remainder, and remove digits from the right by integer division. In both cases, the right operand is some power of 10. For example:
*Main> 123 `mod` 10
3
*Main> 123 `div` 100
1
But how do you know, which power of 10 you should use to divide by? By finding a logarithm base 10: #digits of N = log10N + 1, e.g. log1012345 = 4. Unfortunately you can't use logBase, because it uses floating point arithmetic, which is inaccurate. For example:
*Main> logBase 10 1000
2.9999999999999996
You can use custom function iLogBase for integers—copy the code from the link into your source code. This way to find a first digit of a number I use the following code:
firstDigit :: (Integral a) => a -> a
firstDigit n = n `div` (10^log)
where log = fst $ iLogBase 10 n
Creating a more general function of finding an arbitrary digit of a number and converting a number into a list of digits is left to you as an exercise :).
Also, the code in your question is inefficient. List concatenation (++) operation has the complexity of O(n), that is, every time you want to append an element to and end of list, it has to add the left list to the right list one by one, until you have a resulting list. Check out the source for (++), basically [1,2,3] ++ [4] becomes 1 : 2 : 3 : [4], which is terribly inefficient, as it takes 3 cons (:) operations just to add a list. And as you append numbers to the end multiple times, it has to repeat the same process each time, therefore overall complexity of your function is O(n^2).
On the other hand (:) is instant, that is, has complexity of O(1). No matter how long is your list, prepending an element to the beginning is cheap. So instead of adding an element to the end, I would recommend, adding it to the beginning and an the end simply reversing the list once (for information, Lisp people call this push/nreverse idiom):
reverse $ (n `mod` 10) : toDigits (n `div` 10)