2

I am writing a encrypting program whose process is as follows:

  • Spaces in a message replaced by 'X''s
  • Each word in the original message is reversed
  • Consecutive sequences of words, called “blocks”, have the order of the words reversed. The size of these blocks is a parameter to the encryption function and acts as the “key”. For example, if the message was 'THE PRICE OF FREEDOM IS ETERNAL VIGILENCE' and the block size is four then each block of four words will be reversed, producing 'FREEDOM OF PRICE THE VIGILENCE ETERNAL IS' (ignoring the other two steps above). Notice that the last block only has three words in this case, but it is still reversed nonetheless.

Now I've been able to replace the spaces and reverse everything, but the last step has stumped me.

The following code is what I have so far.

def encrypt (words, block):
    words = words [::-1]
    midpoint = len(words)/block
    first_half = words[0:midpoint]
    second_half = words[midpoint:]
    words = first_half + second_half
    words = words.replace(' ', 'X')
    return words

def decrypt (wordsde, block):
    wordsde = wordsde[::-1]
    midpoint = len(wordsde) / block
    first_half = wordsde[:midpoint]
    second_half = wordsde[midpoint:]
    wordsde = first_half + second_half
    wordsde = wordsde.replace('X', ' ')
    wordsde = wordsde.strip()
    return wordsde

but every time, it can't read the block or something:

File "__main__", line 18, in __main__
Failed example:
    encrypt('WHO WATCHES THE WATCHERS', 2) # Test 4
Expected:
    'SEHCTAWXOHWXSREHCTAWXEHT'
Got:
    'SREHCTAWXEHTXSEHCTAWXOHW'
Trying:
    encrypt('PARANOIA IS OUR PROFESSION', 3) # Test 5
Expecting:
    'RUOXSIXAIONARAPXNOISSEFORP'
**********************************************************************
File "__main__", line 22, in __main__
Failed example:
    encrypt('PARANOIA IS OUR PROFESSION', 3) # Test 5
Expected:
    'RUOXSIXAIONARAPXNOISSEFORP'
Got:
    'NOISSEFORPXRUOXSIXAIONARAP'
Trying:
    encrypt('THE PRICE OF FREEDOM IS ETERNAL VIGILENCE', 4) # Test 6
Expecting:
    'MODEERFXFOXECIRPXEHTXECNELIGIVXLANRETEXSI'
**********************************************************************
File "__main__", line 26, in __main__
Failed example:
    encrypt('THE PRICE OF FREEDOM IS ETERNAL VIGILENCE', 4) # Test 6
Expected:
    'MODEERFXFOXECIRPXEHTXECNELIGIVXLANRETEXSI'
Got:
    'ECNELIGIVXLANRETEXSIXMODEERFXFOXECIRPXEHT'
TerryA
  • 58,805
  • 11
  • 114
  • 143
  • Tested in Python 2.7 and Python 3.1. Both with no errors and the `Got` output was always correct. Are you throwing the output into some other function? Why does it expect `SEHCTAWXOHWXSREHCTAWXEHT`? That's `THE WATCHERS` and `WHO WATCHES`. The second `WHO WATCHES` and `THE WATCHERS` is wrong due to what expectation? –  Mar 31 '13 at 10:57
  • @Allendar Notice the second point. It's rather tricky to explain, but I'll try. Pretend you have `'Foo bar cabbage trees'` (lol). Now let's pretend the block number is 2. That means, every two words, reverse them both. E.G. `'Foo bar cabbage trees'` would go to `'bar Foo trees cabbage'`. Think of it like lists: `'[['Foo','bar'], ['cabbage','trees']]'`. Notice two words in each list (same number as the block) and then you reverse both lists. – TerryA Mar 31 '13 at 11:24
  • 5
    Please don't blank your questions; they might be useful to someone else. – nneonneo Apr 03 '13 at 05:04

1 Answers1

1

This was a brilliant question to answer.

sentence = 'WHO WATCHES THE WATCHERS'
def chunker(seq, size):
    return (seq[pos:pos + size] for pos in xrange(0, len(seq), size)) # Thanks to http://stackoverflow.com/questions/434287/what-is-the-most-pythonic-way-to-iterate-over-a-list-in-chunks/434328#434328
def encrypt(phrase,block):
    l = []
    for g in chunker(phrase.split(),block):
         l.extend(i[::-1] for i in reversed(g))
    return 'X'.join(l)

When tested:

>>> encrypt(sentence,2)
'SEHCTAWXOHWXSREHCTAWXEHT'

>>> 'RUOXSIXAIONARAPXNOISSEFORP' == encrypt('PARANOIA IS OUR PROFESSION', 3)
True

# Strings mentioned above and below were your expected answers 
# mentioned in the question

>>> 'MODEERFXFOXECIRPXEHTXECNELIGIVXLANRETEXSI' == encrypt('THE PRICE OF FREEDOM IS ETERNAL VIGILENCE', 4)=
True
TerryA
  • 58,805
  • 11
  • 114
  • 143
  • AH I LOVE YOU SO MUCH THANK YOU – user2229040 Mar 31 '13 at 11:25
  • Concrete suggestions for improvement: (1) don't need `list` around `reversed` if you are just doing iteration, (2) use `l.extend` to avoid having to join twice (this simplifies the third line of `encrypt` to `l.extend(i[::-1] for i in reversed(g)`), (3) call the first parameter `phrase` not `word`. Otherwise a nice solution (+1). – nneonneo Mar 31 '13 at 11:27
  • I know im pushing my luck here, but if i were to decrypt the phrase into a normal sentence, would i just have to reverse your code? or is it more complicated than that? – user2229040 Mar 31 '13 at 11:28
  • Thank you user229040. nneonneo: Thanks for the suggestions! I have changed my code accordingly. – TerryA Mar 31 '13 at 11:32
  • @user2229040 Alas the decrypt wouldn't be the reversed. Your string that you encrypted may have an `X` in it, making this quite hard. I guess I'm not as advanced enough to do that. Sorry. – TerryA Mar 31 '13 at 11:35
  • im very new to this and only joined tonight, ill make a new question for the decrypter. i hope you can take some time to look at it :) – user2229040 Mar 31 '13 at 11:41
  • @user2229040 Will do :). But now I must sleep :(. Not to be a bother, but could you please accept the answer (click the tick under the amount of votes) to show that this answer helped you the most :). Thanks – TerryA Mar 31 '13 at 11:43
  • FOLLOW UP - http://stackoverflow.com/questions/15729363/assistance-required-beginner-python – user2229040 Mar 31 '13 at 12:27