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 -> ???
Related
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.
I am trying to write a program in Haskell to split a string by delimiter.
And I have studied different examples provided by other users. An example would the the code that is posted below.
split :: String -> [String]
split [] = [""]
split (c:cs)
| c == ',' = "" : rest
| otherwise = (c : head rest) : tail rest
where
rest = split cs
Sample Input: "1,2,3".
Sample Output: ["1","2","3"].
I have been trying to modify the code so that the output would be something like ["1", "," , "2", "," , "3"] which includes the delimiter in the output as well , but I just cannot succeed.
For example, I changed the line:
| c == ',' = "" : rest
into:
| c == ',' = "," : rest
But the result becomes ["1,","2,","3"].
What is the problem and in which part I have had a misunderstanding?
If you're trying to write this function "for real" instead of writing the character-by-character recursion for practice, I think a clearer method is to use the break function from Data.List. The following expression:
break (==',') str
breaks the string into a tuple (a,b) where the first part consists of the initial "comma-free" part, and the second part is either more string starting with the comma or else empty if there's no more string.
This makes the definition of split clear and straightforward:
split str = case break (==',') str of
(a, ',':b) -> a : split b
(a, "") -> [a]
You can verify that this handles split "" (which returns [""]), so there's no need to treat that as a special case.
This version has the added benefit that the modification to include the delimiter is also easy to understand:
split2 str = case break (==',') str of
(a, ',':b) -> a : "," : split2 b
(a, "") -> [a]
Note that I've written the patterns in these functions in more detail than is necessary to make it absolute clear what's going on, and this also means that Haskell does a duplicate check on each comma. For this reason, some people might prefer:
split str = case break (==',') str of
(a, _:b) -> a : split b
(a, _) -> [a]
or, if they still wanted to document exactly what they were expecting in each case branch:
split str = case break (==',') str of
(a, _comma:b) -> a : split b
(a, _empty) -> [a]
Instead of altering code in the hope that it matches the expecations, it is usually better to understand the code fragment first.
split :: String -> [String]
split [] = [""]
split (c:cs) | c == ',' = "" : rest
| otherwise = (c : head rest) : tail rest
where rest = split cs
First of all we better analyze what split does. The first statement simply says "The split of an empty string, is a list with one element, the empty string". This seems reasonable. Now the second clause states: "In case the head of the string is a comma, we produce a list where the first element is an empty string, followed by splitting up the remainings of the string.". The last guard says "In case the first character of the string is not a comma, we prepend that character to the first item of the split of the remaining string, followed by the remaining elements of the split of the remaining string". Mind that split returns a list of strings, so the head rest is a string.
So if we want to add the delimiter to the output, then we need to add that as a separate string in the output of split. Where? In the first guard. We should not return "," : rest, since the head is - by recursion - prepended, but as a separate string. So the result is:
split :: String -> [String]
split [] = [""]
split (c:cs) | c == ',' = "" : "," : rest
| otherwise = (c : head rest) : tail rest
where rest = split cs
That example code is poor style. Never use head and tail unless you know exactly what you're doing (these functions are unsafe, partial functions). Also, equality comparisons are usually better written as dedicated patterns.
With that in mind, the example becomes:
split :: String -> [String]
split "" = [""]
split (',':cs) = "" : split cs
split (c:cs) = (c:cellCompletion) : otherCells
where cellCompletion : otherCells = split cs
(Strictly speaking, this is still unsafe because the match cellCompletion:otherCells is non-exhaustive, but at least it happens in a well-defined place which will give a clear error message if anything goes wrong.)
Now IMO, this makes it quite a bit clearer what's actually going on here: with "" : split cs, the intend is not really to add an empty cell to the result. Rather, it is to add a cell which will be filled up by calls further up in the recursion stack. This happens because those calls deconstruct the deeper result again, with the pattern match cellCompletion : otherCells = split cs, i.e. they pop off the first cell again and prepend the actual cell contents.
So, if you change that to "," : split, the effect is just that all cells you build will already be pre-terminated with a , character. That's not what you want.
Instead you want to add an additional cell that won't be touched anymore. That needs to be deeper in the result then:
split (',':cs) = "" : "," : split cs
I want to make in Haskell a application that gives from a couple of characters all possibilities. That works with the permutation function. But now I want to add to the output of every word in the list a prefix and a suffix. Like:
Input:
combinations "prefix" "sufix" "randomletters"
Output (something like this)
["prefixrandomletters", "prefixrandomletters","prefixrandomletters","prefixrandomletters","suffixrandomletters","suffixrandomletters","suffixrandomletters","suffixrandomletters","suffixrandomletters",]
Background of the application:
Like scrabble. First the prefix is like 2 letters that the word can start with. Then 2 letters that the word can end with. Then the letters you have in your hand.
You can map a function that adds the prefix:
combinations pre suf letters = prefixed ++ suffixed
where
perms = permutations letters
prefixed = map (\x -> pre ++ x) $ perms
suffixed = ...
The way to solve this is to break the problem down, as you have started doing:
create a function to give every permutation (permutation)
create functions to add the prefix & suffix (\x -> pre ++ x etc)
apply these functions to every permutation (map) to create two lists of words
combine the two lists of words (++)
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..",""]
I have a function, which contains the first 101 characters:
characters :: [String]
characters = [[chr i] |i<-[0..100]]
And what I need to do is to make the next function append to this one permanently, so far I have tried something like this, but this doesn't keep the result.
append :: [String] -> String -> String -> [String]
append characters xs ys = characters ++ [(take 2 (xs++ys))]
So pretty much what I need is to be able to continuously expand my characters function with the append function, and not lose the results.
Thanks for the answers.
Values are immutable in Haskell, so
characters ++ somethingElse
produces a new list, containing a copy of characters at the front, characters itself remains unchanged.
So, as stated, your task is impossible. What are the actual requirements?
I don't know, what you're trying to do with your example. But to answer just your subject, you can import with the hiding-flag and write your own version of a function, like:
import Data.Text hiding (append)
HTH