0

I have a string containing the whole alphabet and then I want a different string from it by choosing a keyword and adding it to an exact position and then ordering the rest of the characters of the alphabet.

For example with a keyword gamer and a starting position given by 'l' the result should be -> "abcdefghijklmnopqrstuvwxyz" "opqstuvwxyzgamerbcdfhijkln"

I have seen this is used in the modified caesar cipher but I haven't found a solution for this part of the algorithm.

================================================================================= Now what I have been able to write is the following :

import List
derange key char = (fst(divided char)\\key) ++ key ++ (snd(divided char)\\key)
abc = ['a'..'z']
divided char = break (char==) abc

and the given output for an example is ->

Main> derange "ploting" 'g'

"abcdefplotinghjkmqrsuvwxyz"

So from the position of 'g' I wrote the keyword "ploting" and the rest of the alphabet is added without duplicate characters.

But still there is a little problem because the rest of the alphabet should continue from the first possible character after the keyword. So instead the right output should be "uvwxyzplotingabcdefhjkmqrs".

Change

So I worked on the code, to obtain the result I wanted. At first I tried it with concrete given values for the keyword and the character. What I have come to is the following :

`concat[drop (length['a'..'z'] - index('a','z') 'l') "gamerbcdfhijklnopqstuvwxyz",take    (length['a'..'z'] - index('a','z') 'l') "gamerbcdfhijklnopqstuvwxyz"]`

And the result is

"opqstuvwxyzgamerbcdfhijkln" 

,just what I wanted.

But then I tried to generalize the code so I wrote this.

import List
derange key char = concat [drop (length abc - index('a','z') char) def, 
take (length abc - index('a','z') char) def]
where abc = ['a'..'z']
def = key ++ (key\\abc)

But now the output is

Main> derange "gamer" 'l'
"gamer" 

and I don't know why. Any suggestions?

Found the problem, just had to swap key and abc within the list difference. Now I get the desired output.

  • 2
    Are you expecting there to be a library for this? I would highly doubt this exists as a standard function, you'd have to implement it yourself. What have you tried so far? – bheklilr Apr 04 '14 at 15:43
  • I also doubt there is a given function to this. I know it needs to be written as something new. I thought at first about splitting the alphabet at the particular position given by a character so I wrote abc = ['a'..'z'] a given output for example : divided 'l' ("abcdefghijk","lmnopqrstuvwxyz") But I am not sure if this is a right direction of how to attempt to make this and what should be the next step. Another idea what comes into my mind now is to rotate at first the alphabet so it begins on the given position and then somehow write there the keyword - the duplicate chars. – user3495272 Apr 04 '14 at 18:15
  • You could use your `divided` function, then use `filter` on both sections to remove the duplicated, then join them together with your target string. Could you edit your question with your attempt and maybe a further explanation of what you're wanting to do? I'd vote to reopen if you showed some code. – bheklilr Apr 04 '14 at 18:24
  • Was working on it so it took some time. I also added the code. – user3495272 Apr 04 '14 at 20:29
  • You could solve part of your problem by just swapping the `fst` and `snd` in your code above, but you have to choose where to break intelligently. How might you find the "largest" letter in a `String`, i.e. the one closest to `'z'`? Hint: `Char` is an instance of `Ord`. – bheklilr Apr 04 '14 at 20:43
  • I thought about swapping those two parts but then the positioning is wrong. As you mentioned to find the closest to 'z' I am not sure how that helps because it isn't the `'z' letter` where it should break. Doesn't it have to be something with the indexes in the string? I thought of joining the substring like this : `keyword ++ fst ++ snd`(shortened it for the example) And then to get `25 - index ('a','z') char` -> which gives me the position of where to break this and then also join them together, but is it gonna work somehow? How to add this as the condition for the break function? – user3495272 Apr 05 '14 at 11:08
  • Correct, you don't want to break on `z`, you want to break on the letter closest to `z` in your inserted string, or so it appears from your examples. In order to figure out which letter is furthest along in the alphabet, you can take advantage of `Char`'s `Ord` instance and use a function like `maximum`, e.g. `maximum "gamer"` returns `'r'`, and `maximum "ploting"` returns `'t'`. You can then feed that into your `divided` function. – bheklilr Apr 05 '14 at 13:52
  • What rotation of the string is acceptable? For example, instead of `"stuvwxyzgamerbcdfhijklnopq"` can it be `"qstuvwxyzgamerbcdfhijklnop"` or `"gamerbcdfhijklnopqstuvwxyz"` ? – erisco Apr 06 '14 at 10:05
  • I realized I forgot to mention the desired character in the example so I edited the question. And therefore the rotation depends on the given keyword and a character from which the keyword begins. So as to your question the rotation differs with the given character and also with the keyword (that cannot have duplicate characters either). – user3495272 Apr 06 '14 at 12:15

1 Answers1

1

Your question is a little unclear on what the expected behaviour of derange is supposed to be. This seems to match your description

import Data.List ((\\))

-- returns the 0-based index of c in ['a' .. 'z']
index :: Char -> Int
index c = fromEnum c - 97

derange :: Char -> String -> String
derange key str =
    drop (i - length str) (tail bs ++ str ++ as)
    where (as, bs) = splitAt i $ ['a' .. 'z'] \\ str
          i = index key

sample output,

λ. derange 'g' "ploting"
"jkmqrsuvwxyzplotingabcdef"
cdk
  • 6,698
  • 24
  • 51