3
\$\begingroup\$

Suppose I have a string with a length always a multiple of four:

'CodeReviewSE'

My goal is to create a permutation. First, I arrange the string into a matrix (where each row has a length of 4):

 C o d e
 R e v i
 e w S E

And then I simply read down, starting from the top-left corner. I get four segments: CRe, oew, dvs and eiE. I concatenate them, to get the following string:

'CReoewdvSeiE'

Reversing the operation is just reversing the steps, kinda. It follows the same steps, except for row length are len(text) / 4, and we read down again, to look like this:

 C R e
 o e w
 d v S
 e i E

I've implemented the following code in Python:

import collections
def permute(text):
 # type: (str) -> str
 rows = collections.deque()
 output = ''
 # Create matrix
 for i in xrange(0, len(text), 4):
 rows.append(text[i:i+4])
 # Read matrix downwards
 for counter in xrange(4):
 for row in rows:
 output += row[counter]
 return output
def unpermute(text):
 # type: (str) -> str
 rows = collections.deque()
 output = ''
 length = len(text) / 4
 # Create matrix
 for i in xrange(0, len(text), length):
 rows.append(text[i:i+length])
 # Now read downwards
 for counter in xrange(length):
 for row in rows:
 output += row[counter]
 return output

I also ran a performance tests using the timeit module, using random strings of different lengths (where n is the length):

n = 32 Best: | Avg
Permute: (10,000 loops, best of 10): 0.06563 0.07080
Unpermute: (10,000 loops, best of 10): 0.06337 0.06655
n = 64 Best: | Avg
Permute: (10,000 loops, best of 10): 0.11592 0.11939
Unpermute: (10,000 loops, best of 10): 0.10358 0.10530
n = 256 Best: | Avg
Permute: (10,000 loops, best of 10): 0.43404 0.44310
Unpermute: (10,000 loops, best of 10): 0.37202 0.38102
n = 1024 Best: | Avg
Permute: (10,000 loops, best of 10): 1.82779 1.85647
Unpermute: (10,000 loops, best of 10): 1.72195 1.78491
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Sep 1, 2016 at 2:28
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Most important comment: permute is just unpermute with length = 4.

There seems to be no reason to favor collections.deque over a normal list here. It is only an advantage of you do a lot of queue.popleft() calls.

For the creation of rows you can just use a list comprehension:

rows = (text[i:i+4] for i in xrange(0, len(text), 4))

I would use a generator expression here to save memory

You could simplify your un-/permute to: something like:

def permute(text, n=4, reverse=False):
 n = len(text)/n if reverse else n
 matrix = (text[i:i+n] for i in range(0, len(text), n))
 matrix_t = zip(*matrix)
 return "".join("".join(x) for x in matrix_t)

where (text[i:i+n] for i in range(0, len(text), n)) makes a generator object that is like your rows, zip(*list) transposes a list of lists and the two joins first join each row and then the rows.

This will not even create a lot of overhead because they are all generator objects (and therefore it is not one possibly big list being read into memory).

You could even inline all of it:

def permute(text, n):
 return "".join("".join(x) for x in zip(*(text[i:i+n] for i in range(0, len(text), n))))
answered Sep 1, 2016 at 7:57
\$\endgroup\$
4
  • \$\begingroup\$ "permute is just unpermute with length = 4" should be bolded / underlined in my opinion, merging these functions avoids massive repetition. \$\endgroup\$ Commented Sep 1, 2016 at 11:48
  • \$\begingroup\$ Oh wow. This answer is awesome. I never thought about using zip here, and it does exactly what I want to do. The generator objects are better too. Thank you so much :) \$\endgroup\$ Commented Sep 1, 2016 at 16:44
  • \$\begingroup\$ Nah, it's waaay better! With random strings of length 1024, permuting only takes 0.868s on my machine, way faster than the 1.828s I had before. \$\endgroup\$ Commented Sep 1, 2016 at 16:47
  • \$\begingroup\$ Yay, that wasnt even my goal :-) \$\endgroup\$ Commented Sep 1, 2016 at 21:24

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.