patternpythonMinor
Making a string by reading down a matrix
Viewed 0 times
readingdownmakingmatrixstring
Problem
Suppose I have a string with a length always a multiple of four:
My goal is to create a permutation. First, I arrange the string into a matrix (where each row has a length of 4):
And then I simply read down, starting from the top-left corner. I get four segments:
Reversing the operation is just reversing the steps, kinda. It follows the same steps, except for row length are
I've implemented the following code in Python:
I also ran a performance tests using the
`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:
'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:
Solution
Most important comment:
There seems to be no reason to favor
For the creation of
I would use a generator expression here to save memory
You could simplify your un-/permute to: something like:
where
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:
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))))Code Snippets
rows = (text[i:i+4] for i in xrange(0, len(text), 4))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)def permute(text, n):
return "".join("".join(x) for x in zip(*(text[i:i+n] for i in range(0, len(text), n))))Context
StackExchange Code Review Q#140171, answer score: 3
Revisions (0)
No revisions yet.