Haskell: Converting strings into sentences - haskell

Im learning haskell and I got a problem.
The type must be: sentences :: [String] -> [String]
I want to convert strings into a sentence
["something","","Asd dsa abc","hello world..",""]
to look like this: ["Something.","Asd dsa abc.","Hello world..."]
And I want to use a higher-order function like map.
I just cant figure out how to make this.
I managed to work with a single string:
import Data.Char
sentences :: String -> String
sentences [] = []
sentences (a:as) = (( toUpper a):as) ++ "."
So I get from this:
sentences "sas das asd"
this: "Sas das asd."
I hope someone can help me with this problem.
Thanks for your help!
Edit: Thanks for your help now it looks like this:
import Data.Char
sentences :: [String] -> [String]
sentence (a:as) = ((toUpper a):as)++['.']
sentences = map sentence
But i dont know where to put the filter

Your function coupled with map gets you half of the way, but it does not remove the empty strings from your list of strings. You can do this with filter, so in total
sentences ss = map sentence $ filter (/="") ss
Note that the core of sentences (plural) is simply the mapping of sentence (singular) over your list of strings. The filter is only there to remove the empty strings. Without this requirement, it would simply be sentences ss = map sentence ss.
Now you can call sentences with your list of strings to have each element transformed, except the empty strings that are removed by filter
In general, if you have a function foo that transforms bar into baz, you can use map foo to transform [bar] into [baz]
filter, like map, is a higher order function which, given a predicate function and a list, returns a list consisting of the elements for which the predicate is True. In this case, we give the predicate function (/=""), which is True for all strings that are not empty.

You could also do it with a list comprehension
import Data.Char
capFirst (l:ls) = toUpper l : ls ++ "."
sentences strings = [
capFirst sentence | sentence <- strings,
sentence /= []
]
main = print $ sentences ["something","","Asd dsa abc","hello world..",""]

Related

Implementing rotors

How can I pattern match 2 strings in Haskell? Like let's say I have one string which is all the alphabets "ABCDEFGHIJKLMNOPQRSTUVWXYZ" and another string "EKMFLGDQVZNTOWYHXUSPAIBRCJ". It's like a ciphering thing, where I want to pattern match both these strings so that when I type HELLO in plain text using the normal alphabets, I get "QLTTY".
Let's save these strings so we have some convenient names.
a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
b = "EKMFLGDQVZNTOWYHXUSPAIBRCJ"
Now if you zip them together you get a lookup table.
ghci> cypher = zip a b
ghci> cypher
[('A','E'),('B','K'),('C','M'),('D','F'),('E','L'),('F','G'),('G','D'),('H','Q'),('I','V'),('J','Z'),('K','N'),('L','T'),('M','O'),('N','W'),('O','Y'),('P','H'),('Q','X'),('R','U'),('S','S'),('T','P'),('U','A'),('V','I'),('W','B'),('X','R'),('Y','C'),('Z','J')]
You now simply need to map your string to a lookup on this cypher.
map (\ch -> ...) "HELLO"
This should give you a nudge in the right direction.

Creating an array of possible string variations

I'm trying to figure out how I would create variations of a string, by replacing one character at a time in the string with a different character from another array.
For example:
variations = "abc"
getVariations "xyz" variations
Should return:
["xbc", "ybc", "zbc", "axc", "ayc", "azc", "abx", "aby", "abz"]
I'm not quite sure how to go about this. I tried iterating through the string, and then using list comprehension to add the possible characters but I end up losing characters.
[c ++ xs | c <- splitOn "" variations]
Where xs is the tail of the string.
Would someone be able to point me in the right direction please?
Recursively you can define getVariations replacements input
if input is empty, the result is ...
if input is (a:as), combine the results of:
replacing a with a character from replacements
keeping a the same and performing getVariations on as
This means the definition of getVariations could look ike:
getVariations replacements [] = ...
getVariations replacements (a:as) = ...#1... ++ ...#2...
It might also help to decide what the type of getVariations is:
getVariations :: String -> String -> ???

Haskell counting words containing specific characters in strings

is it possible to get the number of words which contain a specific character from a string ?
for example: string = "yes no maybe"
it would return 2 if the specific character was 'e'.
I have been trying for hours :(
thanks
One way of doing this (shown as a GHCi session) is:
λ> let w = "yes no maybe"
λ> length $ filter (elem 'e') (words w)
2
We split the string into words using the words function.
Then filter the list of words using elem and our chosen character.
Then finally count the number of words that contained the character, using length.
Can also be written as:
length . filter (elem 'e') $ words w
composing the length and filter functions, then applying the combined function to the list of words.

Are two strings anagrams or not?

I want to find if two strings are anagrams or not..
I thought to sort them,and then check one by one but is there any algorithms for sorting stings? or another idea to make it? (simple ideas or code because i am a beginner )thanks
Strings are lists of characters in Haskell, so the standard sort simply works.
> import Data.List
> sort "hello"
"ehllo"
Your idea of sorting and then comparing sounds fine for checking anagrams.
I can give you and idea-(as I am not that much acquainted with haskell).
Take an array having 26 spaces.
Now for each character in the first string you increase certaing position in array.
If array A[26]={0,0,...0}
Now if you find 'a' then put A[1]=A[1]+1;
if 'b' then A[2]=A[2]+1;
Now in case of 2nd string for each character you decrease the values for each character found in the same array.(if you find 'a' decrease A[1] like A[1]=A[1]-1)
At last check if all the array elements are 0 or not. If 0 then definitely they are anagram else not an anagram.
Note: You may extend this for Capital letters similarly.
It is not necessary to count the crowd each letter.
Simply, you can sort your string and then check each element of two lists.
For example, you have this
"cinema" and "maneci"
It would be helpful to make your string into a list of characters.
['c','i','n','e','m','a'] and ['m','a','n','e','c','i']
Then , you can sort these list and you will check each character.
Note that you will have these cases :
example [] [] = True
example [] a = False
example a [] = False
example (h1:t1)(h2:t2) = if h1==h2 then _retroactively_ else False
In the Joy of Haskell "Finding Success and Failure", pp.11-14, the authors offer the following code which works:
import Data.List
isAnagram :: String -> String -> Bool
isAnagram word1 word2 = (sort word1) == (sort word2)
After importing your module (I imported practice.hs into Clash), you can enter two strings which, if they are anagrams, will return true:
*Practice> isAnagram "julie" "eiluj"
True

filtering the words ending with "ed" or "ing" using haskell

hi am new to Haskell and functional programing..
i want to pass in the string and find the words ending with "ed" or "ing".
eg: if the string is "he is playing and he played well"
answer should be : playing, played
does anyone know how to do this using Haskell.
You can build this using standard Haskell functions. Start by importing Data.List:
import Data.List
Use isSuffixOf to determine if one list ends with another. Below endings could be ["ed","ing"] and w would be the word you're testing, such as "played".
hasEnding endings w = any (`isSuffixOf` w) endings
Assuming you have split the string into a list of individual words (ws below), use filter to eliminate the words you don't want:
wordsWithEndings endings ws = filter (hasEnding endings) ws
Use words to get the list of words from the original string. Use intercalculate to join the filtered words back into the final comma-separated string (or leave this off if you want the result as a list of words). Use . to chain these functions together.
wordsEndingEdOrIng ws = intercalate ", " . wordsWithEndings ["ed","ing"] . words $ ws
And you're done.
wordsEndingEdOrIng "he is playing and he played well"
If you're typing into ghci, put let in front of each of the function definitions (all lines but the last one).
contain w end = take (length end) (reverse w) == reverse end
findAll ends txt = filter (\w -> any (contain w) ends) (words txt)
main = getLine >>= print . findAll ["ing","ed"]
findAll :: [String] -> String -> [String]
findAll :: "endings" -> "your text" -> "right words"

Resources