I'm trying to write a function of the form:
f :: String -> [String]
f st = ...
It should display all possible transposions of chars in the String.
For example:
ghci> f "string"
["tsring","srting","stirng","strnig","strign"]
As you can see it should only transpose the next char with the current one.
I currently have:
f :: String -> [String]
f [] = []
f (x:xs) = ...
but i dont know how to actually transpose the chars.
f :: String -> [String]
f (x:y:xs) = (y:x:xs) : map (x:) (f (y:xs))
f xs = []
Note, that f [x] returns [], but it's easy to fix, if this is desired.
Related
I want to make a function that removes a given character from a string.
The prototype is: removeChar :: Char -> String -> String
I tried to do something like this:
removeChar a x = foldr (++) [] (map (\x -> filter f x) x)
where
f x = elem a x
this should be enough, String is nothing but a [Char] so just filter it for that char
removeChar::Char->String->String
removeChar a = filter (/=a)
So I'm pretty new to Haskell, and are trying to solve an assignment, I've solved it, but I'm wondering if there is an easier or prettier way to make a function do the same as my wordChange. I'm trying to only use what is already in prelude.
dictionaryChecker _ [] = False
dictionaryChecker word (x:xs) = if elem word (snd x) then True else dictionaryChecker word xs
wordChange :: String -> String
wordChange str = unwords (map (\s -> if length (translate s) > 0 then (translate s)
else if (dictionaryChecker s dictionary) then concat (replicate (length s) "*")
else s) (words str))
translate :: String -> String
translate str = contains str dictionary
contains _ [] = ""
contains str (x:xs) = if elem str (snd x) then fst x else contains str xs
I'd suggest to use the lookup function from Prelude, which takes a key and a list of tuples (a.k.a a dictionary) and returns Maybe value. This simplfies your function a lot. Also, if changeWord uses a dictionary, it should be explicit instead of using a global variable. Below, a partial solution: since it is an assignment I think you should try to complete it ;)
changeWord :: [(String, String)] -> String -> String
changeWord dic s = unwords $ substitute ws
where -- ws is just the list of words s has
ws = words s
-- the function substitute does the word changing recursively. Try to complete it
substitute [] = []
substitute (x:xs) =
case lookup x dic of -- look for x in the dictionary and returns the value if found
Nothing -> undefined --complete
Just y -> undefined --complete
An obfuscated answer: earn a gold star from your professor if you can explain how it works, and be accused of copying from the internet if you can't:
wordChange :: [(String, String)] -> String -> String
wordChange dict = unwords . map (foldr const <*> (`lookup` dict)) . words
Your dictionaryChecker is in essence an any :: Foldable f => (a -> Bool) -> f a -> Bool with elem word . snd as condition:
dictionaryChecker :: (Foldable f, Foldable g, Eq a) => a -> f (b, g a) -> Bool
dictionaryChecker word = any (elem word . snd)
as for a translate, we can work with a section of an infix operator [Haskell-wiki] to make a point-free function:
translate :: String -> String
translate = (`contains` dictionary)
and for contains we can work with a foldr :: Foldable f => (a -> b -> b) -> b -> f a -> b
contains :: (Foldable f, Foldable g, Eq a) => a -> f (String, g a) -> String
contains str = foldr (\x y -> if … then … else …) ""
I leave implementing the … parts as an exercise.
I am trying to create a function that will sort a list of strings in ascending order bases on the number of occurrences of a certain character without using any library functions, but i do want to know how i can use my version of inssort to do this i am bit confused any help appreciated
My code so far returns wrong order,
say i give it
sortwords 'c' ["abcc", "abc", "bbc", "aa"]
i want it to return
["aa", "abc", "bbc", abcc"]
but i get
["abc","bbc","aa","abcc"]
Here is my code:
insert :: Ord b => (a -> b) -> a -> [a] -> [a]
insert f a [] = [a]
insert f a (x:xs) = if f a <= f x then a:x:xs else x : insert f a xs
inssort :: Ord b => (a -> b) -> [a] -> [a]
inssort f [] = []
inssort f [x] = [x]
inssort f (x:xs) = insert f x (inssort f xs)
countocc :: Eq a => a -> [a] -> Int
countocc x [] = 0
countocc x xs = length [x' | x' <- xs, x == x']
sortwords :: Char -> [String] -> [String]
sortwords c [] = []
sortwords c [x]= [x]
sortwords c (x:y:ys) = if countocc c x <= countocc c y then x : sortwords c (y:ys) else y : sortwords c (x:ys)
I won't spoil the whole solution, but here's a hint: it looks like you are trying to reimplement your sorting procedure in sortwords. Don't do that; just reuse inssort directly! Try filling in this replacement function skeleton:
sortwords :: Char -> [String] -> [String]
sortwords c strings = inssort f strings where
f s = ...
What do you think the ... should be?
I'm trying to write a function of the form
f :: String -> [String]
f str = ...
that returns the list of all the strings formed by removing exactly one character from str. For example:
ghci> f "stack"
["tack","sack","stck","stak","stac"]
Because String and [Char] are synonymous, I could use the index, but I know that you should avoid doing that in Haskell. Is there a better way besides using the index?
You could use recursion like so:
f :: [a] -> [[a]]
f [] = []
f (s:ss) = ss : map (s:) (f ss)
The Josh Kirklin's solution as a one-liner:
f = tail . foldr (\x ~(r:rs) -> (x : r) : r : map (x :) rs) [[]]
Maybe a more readable way to describe it is:
gaps :: [a] -> [[a]]
gaps xs = zipWith removeAt [0..] $ replicate (length xs) xs
removeAt i xs = ys ++ zs
where
(ys,_:zs) = splitAt i xs
But practically, it is slower than the other solutions.
So I write a function with the definition
getLastDigits :: String -> String
which finds repeating digits on the end of a String
So, for example.
getLastDigits "1000" should give "000"
getLastDigits "19990299" should give "99"
Coming from a java background I'm not quite sure how to structure this program. I'm thinking of using foldr but I'm fairly sure I can't stop the fold half way when the repeating digits end.
-edit solved. Use the group function.
Okay then, if it is not homework:
lastDigits :: String -> String
lastDigits s = firstDigits . reverse $ s
where firstDigits :: String -> String
firstDigits (x:xs) = x : takeWhile (== x) xs
firstDigits [] = []
import Data.Char (isDigit)
getLastTheSame :: Eq a => (a -> Bool) -> [a] -> [a]
getLastTheSame pred xs = f (reverse xs)
where f (y : ys) | pred y = y : takeWhile (== y) ys
f _ = []
lastDigits :: String -> String
lastDigits = getLastTheSame isDigit
You say you want repeating digits from the end of the string. I presume that if the last character is not a digit then you want the empty string returned.
Recall that type String = [Char].