Haskell transpose chars in String - string

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

How can I remove a certain character from a string in Haskell?

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)

Is there an easier way to write this function and only using prelude from Haskell?

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.

sort a list of strings based on the number of occurrences of a given char in the string

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?

Haskell delete Chars from String

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.

Identifying repeating consecutive digits on the end of a String in haskell

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].

Resources