I am trying to create a shift function using let2nat and nat2let functions.
This shift function applies a shift factor in the range 0 to 25 to a lower-case letter in the range āaā to āzā. Characters outside this range, such as upper-case letters and punctuation, should be returned unshifted. Make sure your function wraps around at the end of the alphabet.
module Kaan where
import Data.Char
let2nat :: Char -> Int
let2nat x = (ord x) - 97
nat2let :: Int -> Char
m = ['a'..'z']
nat2let x = m !! x
shift :: Int -> Char -> Char
shift x y
| (x + let2nat y <= 25) && (x + let2nat y >= 0) = nat2let x + let2nat y
| (x + let2nat y) > 25 = nat2let (x+let2nat y) `mod` 25
| Otherwise = y
main = do
print $ let2nat 'h'
This is what I am getting : Not in scope: data constructor Otherwise`
The binding is named otherwise with a lowercase o. otherwise is defined to be the same as True in the Prelude.
Incidentally, anything (at a value-level) that begins with an uppercase character is a data constructor not a normal binding like otherwise.
Related
I want to create a function as mentioned in the title. The specific is that it adds the digits in reversed order, you can see that in the test cases: 12 -> 1; 852369 -> 628; 1714 -> 11; 12345 -> 42; 891 -> 9; 448575 -> 784; 4214 -> 14
The main idea is that when the number is bigger than 99 it enters the helper function which has i - indicator if the the digit is on an even position, and res which stores the result. Helper begins to cycle n as it checks whether or not the current digit is on even position and adds it to the result.
So far I've tried the following code:
everyOther :: Int -> Int
everyOther n
| n < 10 = error "n must be bigger than 10 or equal"
| n < 100 = div n 10
| otherwise = helper n 0 0
where
helper :: Int -> Int -> Int -> Int
helper n i res
| n < 100 = res
| i == 1 = helper (div n 10) (i - 1) (res + (mod n 10)*10)
| otherwise = helper (div n 10) i res
Any help would be appreciated!
You can obtain the one but last digit of x with mod (div x 10) 10. You can use this with an accumulator that accumulates the value by each time multiplying with 10, so:
everyOther :: Int -> Int
everyOther = go 0
where go a v
| v < 10 = a
| otherwise = go (10*a + mod (div v 10) 10) (div v 100)
If v is thus less than 10, we can return the accumulator, since there is no "other digit" anymore. If that is not the case, we multiply a with 10, and add mod (div v 10) 10 to add the other digit to it, and recurse with the value divided by 100 to move it two places to the right.
We can improve this, as #Daniel Wagner says, by making use of quotRem :: Integral a => a -> a -> (a, a):
everyOther :: Int -> Int
everyOther = go 0
where go a v
| v < 10 = a
| otherwise = let (q, r) = v `quotRem` 100 in go (10*a + r `quot` 10) q
here we thus work with the remainder of a division by 100, and this thus avoids an extra modulo.
This is my code:
reverseEncode :: Char -> String -> Int -> Char
reverseEncode _ [] _ = ?
reverseEncode c (x:xs) offset
| alphaPos c == (alphaPos x + offset) `mod` 26 = chr (((alphaPos x + offset) + 65) `mod` 26)
| otherwise = reverseEncode c xs offset
It's just a small method used in a virtual Enigma Machine. After writing the function without the second line and testing it, I got this exception:
Non-exhaustive patterns in function reverseEncode
I then realised I didn't tell the function when to stop recursing. This is how that second line of code was born. Obviously, I could just check the length of the string at each step, but it doesn't look as elegant.
Is there anything in Haskell I can put instead of '?' ? If not, is there anything I can define? Or is this something that could be done in a better way?
EDIT: I've actually tried the version with checking the length of the string, and I get the same exception. So how do I make it work?
There is no empty character. You could however use a character like the Nul character [wiki]. For example with:
reverseEncode :: Char -> String -> Int -> Char
reverseEncode _ [] _ = '\00'
reverseEncode c (x:xs) offset
| alphaPos c == sm `mod` 26 = chr ((sm + 65) `mod` 26)
| otherwise = reverseEncode c xs offset
where sm = alphaPos x + offset
But a more Haskellish approach would be to change the return type. For example by using a Maybe Char instead. This is often used for "computations that can fail". So we could do this with:
reverseEncode :: Char -> String -> Int -> Maybe Char
reverseEncode _ [] _ = Nothing
reverseEncode c (x:xs) offset
| alphaPos c == sm `mod` 26 = Just (chr ((sm + 65) `mod` 26))
| otherwise = reverseEncode c xs offset
where sm = alphaPos x + offset
Here the Nothing thus means we reached the end of the list without meeting the condition, and Just x means that the computation resulted in an answer x.
I am trying to write this function in Haskell called scanString, which takes a string and convert it into int if it's composed of only digits and should return 0 otherwise.
For example, scanString "123" = 123 but scanString "12a" = 0.
Here's my implementation so far:
scanChar :: Char -> Int
scanChar c
| 48 <= fromEnum c && fromEnum c <= 57 = (fromEnum c) - fromEnum '0'
| otherwise = 0
scanString :: String -> Int
scanString str = case str of
[] -> 0
x:xs
| 48 <= fromEnum x && fromEnum x <= 57 ->
((scanChar x) * (10 ^ ((length str) -1 ))) + scanString xs
| otherwise -> 0
This code does not do the right thing as scanString "3a" would give 30.
Is there a way (like in Java or Python) where one can simply terminate a function and return a value? Of course, advice on the implementation on this function would be awesome!
Thanks in advance!
The main problem here I think is that you let scanChar :: Char -> Int return both a zero for the zero character ('0') as well as for other characters. As a result the scanString has to include extra logic and this makes it only more complex.
So we can clean the scanChar by for instance returning a -1 (or we could let it return a Maybe Int and let it return Nothing, regardless how you exactly specify it, the key is to try to encapsulate the checking logic in one function, such that we no longer have to care about it). So for example:
scanChar :: Char -> Int
scanChar c | '0' <= c && c <= '9' = fromEnum c - fromEnum '0'
| otherwise = -1
So now we can encapsulate all the digit parsing logic in scanChar. Now we still need to implement scanString :: String -> Int. This can be done by writing an extra function that works with an accumulator. For example:
scanString :: String -> Int
scanString = go 0
where go a s = ...
So here go acts as a function to emulate some sort of while loop. The a parameter is the accumulator, a parameter we pass through recursive calls and each time we can update it with more data. Initially we set it to zero.
The go function has basically three cases:
the end of the string is reached, we can return the accumulator;
the first character of the string is not a digit, we return 0; and
the first character of the string is a digit, we multiply the accumulator with 10, add the parsed value, and perform recursion on the tail of the string.
We can thus implement those three cases like:
scanString :: String -> Int
scanString = go 0
where go a [] = a
go a (x:xs) | 0 <= sc && sc <= 9 = go (10*a+sc) xs
| otherwise = 0
where sc = scanChar x
So you're limited by the specification of the problem that the outermost question be of type String -> Int, but that doesn't mean that your helper function scanChar can't return Maybe Int.
So let's look at doing that:
scanChar :: Char -> Maybe Int
scanChar c
| 48 <= fromEnum c && fromEnum c <= 57 = Just $ (fromEnum c) - fromEnum '0'
| otherwise = Nothing
Now, using the approach in the other answer:
scanString :: String -> Int
scanString = go 0
where go a [] = a
go a (x:xs) = case (scanChar x) of
Nothing -> 0
Just d -> go (10*a + d) xs
where sc = scanChar x
Why not
scanString :: String -> Int
scanString x = if all (`elem` "0123456789") x
then read x :: Int
else 0
Note: it will not read negative integers.
Or:
import Data.Char (isDigit)
scanString' :: String -> Int
scanString' x = if all isDigit x
then read x :: Int
else 0
Also a simple solution here using readMaybe.
You can make the following into a function with one parameter that is a string. This function will take only digits out of the string and pack them into another string which is then then converted.
[read [d | d <- "12a", elem d "1234567890"] :: Int] !! 0
Yields 12
I want to display some Rational values in their decimal expansion. That is, instead of displaying 3 % 4, I would rather display 0.75. I'd like this function to be of type Int -> Rational -> String. The first Int is to specify the maximum number of decimal places, since Rational expansions may be non-terminating.
Hoogle and the haddocks for Data.Ratio didn't help me. Where can I find this function?
You can make it. Not elegant, but does the job:
import Numeric
import Data.Ratio
display :: Int -> Rational -> String
display n x = (showFFloat (Just n) $ fromRat x) ""
Here is an arbitrary precision solution that doesn't use floats:
import Data.Ratio
display :: Int -> Rational -> String
display len rat = (if num < 0 then "-" else "") ++ (shows d ("." ++ take len (go next)))
where
(d, next) = abs num `quotRem` den
num = numerator rat
den = denominator rat
go 0 = ""
go x = let (d, next) = (10 * x) `quotRem` den
in shows d (go next)
Arbitrary precision version that re-uses library code:
import Data.Number.CReal
display :: Int -> Rational -> String
display digits num = showCReal digits (fromRational num)
I know I've seen a function before that converts rationals into digits in a way that's easier to inspect (i.e. that makes it quite clear where the digits start repeating), but I can't seem to find it now. In any case, it's not hard to write, if that turns out to be a need; you just code up the usual long-division algorithm and watch for divisions you've already done.
Here's one that I wrote a few weeks ago. You can specify the number of decimals you want (correctly rounded), or just pass Nothing in which case it will print the full precision, including marking the repeated decimals.
module ShowRational where
import Data.List(findIndex, splitAt)
-- | Convert a 'Rational' to a 'String' using the given number of decimals.
-- If the number of decimals is not given the full precision is showed using (DDD) for repeating digits.
-- E.g., 13.7/3 is shown as \"4.5(6)\".
showRational :: Maybe Int -> Rational -> String
showRational (Just n) r =
let d = round (abs r * 10^n)
s = show (d :: Integer)
s' = replicate (n - length s + 1) '0' ++ s
(h, f) = splitAt (length s' - n) s'
in (if r < 0 then "-" else "") ++ h ++ "." ++ f
-- The length of the repeating digits is related to the totient function of the denominator.
-- This means that the complexity of computing them is at least as bad as factoring, i.e., it quickly becomes infeasible.
showRational Nothing r =
let (i, f) = properFraction (abs r) :: (Integer, Rational)
si = if r < 0 then "-" ++ show i else show i
decimals f = loop f [] ""
loop x fs ds =
if x == 0 then
ds
else
case findIndex (x ==) fs of
Just i -> let (l, r) = splitAt i ds in l ++ "(" ++ r ++ ")"
Nothing -> let (c, f) = properFraction (10 * x) :: (Integer, Rational) in loop f (fs ++ [x]) (ds ++ show c)
in if f == 0 then si else si ++ "." ++ decimals f
import Data.List as L
import Data.Ratio
display :: (Integral i, Show i) => Int -> Ratio i -> String
display len rat = (if num < 0 then "-" else "") ++ show ip ++ "." ++ L.take len (go (abs num - ip * den))
where
num = numerator rat
den = denominator rat
ip = abs num `quot` den
go 0 = ""
go x = shows d (go next)
where
(d, next) = (10 * x) `quotRem` den
Below I have defined a function that converts a list of base-3 digits to the corresponding numerical value. For example:
f "201" = (2 * 3^2) + (0 * 3^1) + (1 * 3^0) = 19
f "12" = 5
f "1202" = 47
f "120221" = 430
Here is a definition using comprehension:
f :: String -> Int
f str = sum (listToFinal (stringToTuples str))
Helper functions:
-- 1) converts "201" to "102"
reverse "str"
-- 2) converts "102" to 102
stringToInt :: String -> Int
stringToInt str = read str :: Int
-- 3) converts 102 to ['1','0','2']
intToList :: Int -> [Int]
intToList 0 = []
intToList x = intToList (x `div` 10) ++ [x `mod` 10]
-- 4) converts "201" to [(1,0),(0,1),(2,2)] using reverse, stringToInt, intToList
stringToTuples :: String -> [(Int,Int)]
stringToTuples str = zip (intToList (stringToInt (reverse str))) [0..]
-- 5) converts [(1,0),(0,1),(2,2)] to [1*3^0, 0*3^1, 2*3^2]
listToFinal :: [(Int,Int)] -> [Int]
listToFinal list = [ x * (3^y) | (x,y) <- list ]
Now I'd like to do it with recursion only (well, using basic & library functions too, of course).
An idea: I was thinking of taking the head of each element in the list and simply multiplying it with 3^(length of string - 1). The only problem is, with each recursive call the power of three would have to decrease by 1, e.g. given:
recursive_version "201" = (2 * 3^2) + (0 * 3^1) + (1 * 3^0)
How to implement this?
Here is a much simpler approach; note that, through the use of foldl, it's only "implicitly" recursive, though. For information, digitToInt is exported by Data.Char.
import Data.Char
import Data.List ( foldl' )
--- horner x xs : the value of polynomial 'xs' at point 'x'
horner :: Int -> [Int] -> Int
horner x = foldl' (\c1 c0 -> c1 * x + c0) 0
-- f s : the integer whose representation in base 3 is string 's'
f :: String -> Int
f = horner 3 . map digitToInt
When you define it recursively, the natural way to decrement the length is trimming the array from the head. For example:
base3 x = base3' x 0 where
base3' (d:ds) v = base3' ds $ v + d * 3 ^ length ds
base3' [] v = v