Add n spaces between each letter in a given string in Haskell - haskell

I am quite a beginner and I am trying to write a function in Haskell that would take in a number n and a given string. The function will then return the string with n spaces between each letter in the string.
For example the function addSpace 2 "hello" will return the following "h e l l o".
For the moment I have only managed to have a function that would take in a String and just add a single space between each letter.
addSpace :: String -> String
addSpace s = if length s <= 1
then s
else take 1 s ++ " " ++ addSpace (drop 1 s)
However the function in Haskell I would like it to be:
addSpace :: Integer -> String -> String
Appreciate all help!

You already have a working implementation that adds a string between every character of the input string; it's just that the string to be added is hardcoded as " ". So it should be fairly obvious that all you need to do is replace the " " with some function call that takes an Integer and works out how many spaces there should be:
addSpace :: Integer -> String -> String
addSpace n s
= if length s <= 1
then s
else take 1 s ++ makeSpaces n ++ addSpace (drop 1 s)
Now all you have to do is define the makeSpaces function. From how we're using it, it must have this type:
makeSpaces :: Integer -> String
makeSpaces n = _
I'm not going to give you any more code, but you can implement it very similarly to the recursion scheme you already demonstrated in addSpace, only instead of the choice of whether to recurse of not being based on the length of an input string, it will be based on the value of an input integer. When n is zero, what should you return? When it's greater than zero, what should you add to a recursive call to get the right answer? And how should you transform n as input for the recursive call.
For bonus points1: your current addString works (at least for finite inputs) but can be very inefficient, because every time you ask for the length of a string (which you do in every recursive call) it has to walk the entire string to count out the length. Since you don't actually use the length for anything except checking whether it it's less than or equal to 1, do you really need to calculate the exact length? If you've been shown pattern matching2 then you should be able to think of a way to tell whether a list has at least one character in it without calling length.
1 I say "bonus points" because an addSpace :: Integer -> String -> String function based on the way you've written your current solution works and I imagine it would get a decent mark in a beginner course, but I also imagine it will not get a top mark; the code is inefficient and longer than it needs to be.
2 If you haven't been shown pattern matching then (a) you can ignore this whole "bonus points" paragraph, as I don't think it will be required of you to get a good mark, and (b) they're teaching you Haskell in a very weird order.

Related

Haskell - Splitting a string by delimiter

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

Convert string S to another string T by performing exactly K operations (append to / delete from the end of the string S)

I am trying to solve a problem. But I am missing some corner case. Please help me. The problem statement is:
You have a string, S , of lowercase English alphabetic letters. You can perform two types of operations on S:
Append a lowercase English alphabetic letter to the end of the string.
Delete the last character in the string. Performing this operation on an empty string results in an empty string.
Given an integer, k, and two strings, s and t , determine whether or not you can convert s to t by performing exactly k of the above operations on s.
If it's possible, print Yes; otherwise, print No.
Examples
Input Output
hackerhappy Yes
hackerrank
9
5 delete operations (h,a,p,p,y) and 4 append operations (r,a,n,k)
aba Yes
aba
7
4 delete operations (delete on empty = empty) and 3 append operations
I tried in this way (C language):
int sl = strlen(s); int tl = strlen(t); int diffi=0;
int i;
for(i=0;s[i]&&t[i]&&s[i]==t[i];i++); //going till matching
diffi=i;
((sl-diffi+tl-diffi<=k)||(sl+tl<=k))?printf("Yes"):printf("No");
Please help me to solve this.
Thank You
You also need the remaining operations to divide in 2, because you need to just add and remove letters to waste the operations.
so maybe:
// c language - strcmp(s,t) returns 0 if s==t.
if(strcmp(s,t))
((sl-diffi+tl-diffi<=k && (k-(sl-diffi+tl-diffi))%2==0)||(sl+tl<=k))?printf("Yes"):printf("No");
else
if(sl+tl<=k||k%2==0) printf("Yes"); else printf("No");
You can do it one more way using binary search.
Take the string of smaller length and take sub-string(pattern) of length/2.
1.Do a binary search(by character) on both of the string if u get a match append length/4 more character to the pattern if it matches add more by length/2^n else append one character to the original(pattern of length/2) and try .
2.If u get a mismatch for pattern of length/2 reduce length of the pattern to length/4 and if u get a match append next character .
Now repeat the steps 1 and 2
If n1+n2 <= k then the answer is Yes
else the answer is no
Example:
s1=Hackerhappy
s2=Hackerrank
pattern=Hacker // length = 10 (s2 is smaller and length of s2=10 length/2 =5)
//Do a binary search of the pattern you will get a match by steps 1 and 2
n1 number of mismatched characters is 5
n2 number of mismatched characters is 4
Now n1+n2<k // its because we will need to do these much operation to make these to equal.
So Yes
This should work for all cases:
int sl = strlen(s); int tl = strlen(t); int diffi=0;
int i,m;
for(i=0;s[i]&&t[i]&&s[i]==t[i];i++); //going till matching
diffi=i;
m = sl+tl-2*diffi;
((k>=m&&(k-m)%2==0)||(sl+tl<=k))?printf("Yes"):printf("No");

Convert a string into an integer of its ascii values

I am trying to write a function that takes a string txt and returns an int of that string's character's ascii numbers. It also takes a second argument, n, that is an int that specified the number of digits that each character should translate to. The default value of n is 3. n is always > 3 and the string input is always non-empty.
Example outputs:
string_to_number('fff')
102102102
string_to_number('ABBA', n = 4)
65006600660065
My current strategy is to split txt into its characters by converting it into a list. Then, I convert the characters into their ord values and append this to a new list. I then try to combine the elements in this new list into a number (e.g. I would go from ['102', '102', '102'] to ['102102102']. Then I try to convert the first element of this list (aka the only element), into an integer. My current code looks like this:
def string_to_number(txt, n=3):
characters = list(txt)
ord_values = []
for character in characters:
ord_values.append(ord(character))
joined_ord_values = ''.join(ord_values)
final_number = int(joined_ord_values[0])
return final_number
The issue is that I get a Type Error. I can write code that successfully returns the integer of a single-character string, however when it comes to ones that contain more than one character, I can't because of this type error. Is there any way of fixing this. Thank you, and apologies if this is quite long.
Try this:
def string_to_number(text, n=3):
return int(''.join('{:0>{}}'.format(ord(c), n) for c in text))
print(string_to_number('fff'))
print(string_to_number('ABBA', n=4))
Output:
102102102
65006600660065
Edit: without list comprehension, as OP asked in the comment
def string_to_number(text, n=3):
l = []
for c in text:
l.append('{:0>{}}'.format(ord(c), n))
return int(''.join(l))
Useful link(s):
string formatting in python: contains pretty much everything you need to know about string formatting in python
The join method expects an array of strings, so you'll need to convert your ASCII codes into strings. This almost gets it done:
ord_values.append(str(ord(character)))
except that it doesn't respect your number-of-digits requirement.

Given length L find the shortest string formed only of as & bs >= L such that adding some character (Either a or b) doesn't produce a new palindrome

Given length L find the shortest string >= L formed only of as & bs such that adding some character (Either a or b) doesn't produce a new palindrome substring (never seen before palindrome)
For example for L = 1
there is the string aabbaba, adding "a" to it to result in aabbabaa will only produce the palindromes "a" and "aa" which were seen before at the 1st and 2nd character positions,
but for example the string aabab doesn't work because adding "b" or "a" will produce the new palindromes "bb" and "ababa" respectively
I'm not even sure aabbaba is the optimal solution for L = 1.
Any ideas on an algorithm to solve this fast?
Here are my results so far:
L=1-7: "aabbaba" -> "aabbabaa" (or the mirror, confirming your result)
L=8: "aaabbaba" -> "aaabbabaa" (or the mirror)
L=9: "aaaabbbaba" -> "aaaabbbabaa" (or the mirror)
All futher L can be solved just by prefixing an additional a to the starting string.

Does anyone know how to write a function in Haskell to calculate octal into hexadecimal-notation?

I was supposed to write a code in Haskell which calculates the hexadecimal-notation when I have the octal. Unfortunately, I have no Idea how to start and which functions I have to link. Could anyone help me with that?
First read in the octal value (drop the 'o' or other indicator) via readOct. Then, take that Integer and convert it to a hex string using showHex, and decorate as you like.
main = do
octStr <- getLine
let
val :: Integer
(val,_):_ = readOct octStr
hexStr = showHex val ""
putStrLn hexStr
Also, depending on how frequently you do this, you might try and avoid the String type and use either ByteString (with these show like functions) or Text (with these show like functions). Seems octal doesn't get much attention, at least not as much as decimal and hexadecimal.

Resources