I am very new to Haskell and am trying to retrieve 'a' if I give 0, 'b' if I give 1 and so on...
This is my code so far:
alpha = ['a'..'z']
numb = [0..25]
zippedChars = zip alpha numb
and this is the list:
I want to make something like: getCharfromNumb, and if I type getCharfromNumb 0 I should receive 'a'.
And getNumbfromChar 'a' should give me 0.
import Data.List
import Data.Tuple
getCharFromNum :: Int -> Maybe Char
getCharFromNum n = lookup n $ swap <$> zippedChars
getNumFromChar :: Char -> Maybe Int
getNumFromChar c = lookup c zippedChars
See Data.List.lookup, Data.Tuple.swap, and Data.Functor.<$>
Related
I'm tasked with writing a Haskell program that'll prompt the user to input a string, and then the program will assign a number to each letter(e.g. a = 1, d = 4, y = 25, z = 26) and then it will sum the total from the string. Example "Hi" would equal 8 + 9 or 17. I've got something to do the first part but only if its in all caps, but I still can't figure out how to get the output list summed.
import Data.Char
toOrder :: [Char] -> [Int]
toOrder str = map ((\x -> x - 64) . ord) str
Ideas?
You can use toUpper to regularize the characters, and sum to sum the list of Ints:
import Data.Char (ord, toUpper)
main = print $ score "Hi" -- 17
score :: String -> Int
score = sum . map (subtract 64 . ord . toUpper)
Haskell Code Problem
Description: Code is supposed to return how many digits in the number divide the number as a whole.
For example, 12 has two digits [1, 2], both of which divide 2 (12%2 and 12%1 are both 0) so 2 is returned as there are two digits that divide the number.
For 102, 2 is returned as 1 and 2 both divide 102, division by 0 is undefined.
However, with this code I get errors with numbers containing 0s in the middle of the number (e.g. 1001020)
I get "Program Error: Prelude.read: no parse"
Any help will be greatly appreciated. Many thanks.
import Control.Monad
import Data.Array
import Data.Bits
import Data.Char
import Data.List
import Data.Set
import Debug.Trace
import System.Environment
import System.IO
import System.IO.Unsafe
findDigits :: Int -> Int
findDigits n = digits n n 0 (lengths n)
where
digits n on count endCheck
| endCheck == 0 = count
| header n == 0 = digits (tailer n) on count (endCheck-1)
| on `mod` header n == 0 = digits (tailer n) on (count+1) (endCheck-1)
| otherwise = digits (tailer n) on count (endCheck-1)
header :: Int -> Int
header x = digitToInt . head . show $ x
tailer :: Int -> Int
tailer x = read . tail . show $ x
lengths :: Int -> Int
lengths x = length . show $ x
I think you are trying to do too much in a function. Uually it is better to work with small functions that each solve a simple task, and then combine these in functions that are small as well, and perform a (slightly) more sophisticated task.
For example we can make a function digits :: Int -> [Int] that returns a list of digits:
digits :: Int -> [Int]
digits x | x >= 10 = r : digits q
| otherwise = [x]
where (q,r) = quotRem x 10
For example:
Prelude> digits 102
[2,0,1]
We can then filter these digits to check that the digits are not zero (since then it is not dividable), and that the number is dividable by that digit:
dividableDigits :: Int -> [Int]
dividableDigits n = filter (\x -> x /= 0 && mod n x == 0) (digits n)
Now it is a matter of counting the numbers that match. I leave that as an exercise.
Im a beginner to haskell and I've tried to create a function which counts the numbers of a character in a string. The problem I have is that I am only able to count either the number of occurences of a uppercase or a lowercase character. I want to count both of them. E.g. For the string Mum the result for counting m should be 2.
My function right now looks like this:
import Data.Char
countList :: [Char] -> Char -> Int
countList str c = length $ filter (== c) str
What would your suggestions on solving this be?
import Data.Char (toUpper)
countChar :: Char -> [Char] -> Int
countChar char = length . filter (\c -> toUpper c == toUpper char)
countChar 's' "Stdudents" => 2
countChar 'S' "Sstudents" => 3
countChar 'S' "$tudent$$" => 0
Given a character 'char', filter the entire string for any character whose uppercase matches the uppercase of 'char'. Feed the new filtered string to the 'length' function to get the total count.
A neat way to obtain the toUpper c == toUpper char comparison is to use the on combinator:
import Data.Function
countChar char = length . filter (on (==) toUpper char)
Just transform all to lowercase:
import Data.Char
countList :: [Char] -> Char -> Int
countList str c = length $ filter (== toLower c) $ map toLower str
You can also use just use fold, here a ghci example:
Prelude Data.Char> let countList = \str c -> foldl (\x y -> x + if ((toLower y) == (toLower c)) then 1 else 0) 0 str
Prelude Data.Char> countList "AAaabCC" 'a'
4
I'm trying to write a Caesar cipher but with only uppercase alphanumeric. Using ord or chr uses the whole ASCII table. How can accomplish this?
This is what I have so far:
alphabet = ['A'..'Z'] ++ ['0'..'9']
c2I = ord c - ord 'A'
i2C = chr (n + ord 'A')
the basic idea is to use mod to wrap around to the beginning.
Now it's not efficient (but hey you are using the most unsecure cipher so you might not care to much) but I'll show you using just the alphabet and indexing functions:
import Data.List (elemIndex)
alphabet :: [Char]
alphabet = ['A'..'Z'] ++ ['0'..'9']
ith :: Int -> Char
ith i = alphabet !! j
where j = i `mod` length alphabet
index :: Char -> Int
index c = case c `elemIndex` alphabet of
Just i -> i
Nothing -> error "not inalphabet"
encode :: Int -> String -> String
encode n xs = [ ith $ index x + n | x <- xs ]
this will give you
λ> encode 3 "ABCXYZ012789"
"DEF012345ABC"
now you probably will want to find a way using ord and chr - both works if you make a case distinction between A-Z and 0-9, because the ranges are:
65-90 for A-Z
48-57 for 0-9
so you cannot take a one formula without to many tricks
You should try but it's more math from here (you'll probably want something like ord c - ord 'A' for letters and 26 + ord c - ord '0' for digits to get it in the range 0-35 first.
If I had a known list A :: [Int], and wanted to get a new list B = newList A with newList defined as the following:
newList :: [Int] -> [Int]
newList [] = []
newList (a:as) | a==0 = f(a) : newList (as)
| a==1 = g(a) : newList (as)
| otherwise = h(a) : newList (as)
where f, g, h :: Int -> Int are unimportant functions.
Other than B, I also wanted to know how many 0, 1 are there in A respectively.
But since when producing B recursively, it has already checked whether a== (0 or 1) for each elements in A, so it's a redundancy to check it again separably.
Is it possible to get B but at the same time get how many 0, 1 are there in A with checking only once?
This is not an answer you are looking for, but there is a nice abstract structure behind your function, so I'll leave it here:
import Data.Monoid
import Data.Functor
import Data.Traversable
import Control.Arrow
import Control.Monad.Trans.Writer
wr :: Int -> Writer (Sum Int, Sum Int) Int
wr 0 = tell (Sum 1, Sum 0) $> f 0
wr 1 = tell (Sum 0, Sum 1) $> g 1
wr n = return $ h n
collect :: [Int] -> ([Int], (Int, Int))
collect = second (getSum *** getSum) . runWriter . traverse wr
Summing is a monoid, double summing is a monoid, the Writer monad handles monoids, traverse maps a list with an effectful function and performs all effects.
This:
f = (+ 1)
g = (+ 2)
h = (+ 3)
main = print $ collect [0, 1, 2, 3, 0, 0, 0, 4, 1]
prints ([1,3,5,6,1,1,1,7,3],(4,2)) — four zeros and two ones.