Square code encode and decode

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
2
down vote

favorite












I am doing some python practice and wrote a square code encoder/decoder. As described in drill #4 of Programming Practice Problems, the characters of a message are written left-to-right on a square grid, and each line of the encoded message is read by going top to bottom.



I'd like some feedback on what I wrote to see if there is anything I could have done better:



import math


def encode(message):
message = message.replace(" ", "")
square = math.ceil(math.sqrt(len(message)))

# Create the "grid"
rows =
for row in range(square):
pos = row * square
code = message[pos:pos + square]
rows.append(code)

print("The grid:n".format("n".join(rows)))

# Encode the message
coded_msg = ""
for col in range(square):
for row in range(square):
# The last column of the last row will throw an out of range error, so handle that
if col < len(rows[row]):
coded_msg += rows[row][col]
coded_msg += " "

return coded_msg.rstrip()


def decode(message):
square = math.sqrt(len(message))
col_count = math.ceil(square)
row_count = math.ceil(len(message) / col_count)

cols = message.split(" ")

decoded_msg = ""
for row in range(row_count):
for col in cols:
if row < len(col):
decoded_msg += col[row]

return decoded_msg


if __name__ == "__main__":

print("Gimme a message:")
in_message = input()

coded_message = encode(in_message)
print("--nSquare message:n".format(coded_message))
decoded_message = decode(coded_message)
#print("--nDecoded message:n".format(decoded_message))

print("--ninput: noutput: ".format(in_message, decoded_message))






share|improve this question



























    up vote
    2
    down vote

    favorite












    I am doing some python practice and wrote a square code encoder/decoder. As described in drill #4 of Programming Practice Problems, the characters of a message are written left-to-right on a square grid, and each line of the encoded message is read by going top to bottom.



    I'd like some feedback on what I wrote to see if there is anything I could have done better:



    import math


    def encode(message):
    message = message.replace(" ", "")
    square = math.ceil(math.sqrt(len(message)))

    # Create the "grid"
    rows =
    for row in range(square):
    pos = row * square
    code = message[pos:pos + square]
    rows.append(code)

    print("The grid:n".format("n".join(rows)))

    # Encode the message
    coded_msg = ""
    for col in range(square):
    for row in range(square):
    # The last column of the last row will throw an out of range error, so handle that
    if col < len(rows[row]):
    coded_msg += rows[row][col]
    coded_msg += " "

    return coded_msg.rstrip()


    def decode(message):
    square = math.sqrt(len(message))
    col_count = math.ceil(square)
    row_count = math.ceil(len(message) / col_count)

    cols = message.split(" ")

    decoded_msg = ""
    for row in range(row_count):
    for col in cols:
    if row < len(col):
    decoded_msg += col[row]

    return decoded_msg


    if __name__ == "__main__":

    print("Gimme a message:")
    in_message = input()

    coded_message = encode(in_message)
    print("--nSquare message:n".format(coded_message))
    decoded_message = decode(coded_message)
    #print("--nDecoded message:n".format(decoded_message))

    print("--ninput: noutput: ".format(in_message, decoded_message))






    share|improve this question























      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      I am doing some python practice and wrote a square code encoder/decoder. As described in drill #4 of Programming Practice Problems, the characters of a message are written left-to-right on a square grid, and each line of the encoded message is read by going top to bottom.



      I'd like some feedback on what I wrote to see if there is anything I could have done better:



      import math


      def encode(message):
      message = message.replace(" ", "")
      square = math.ceil(math.sqrt(len(message)))

      # Create the "grid"
      rows =
      for row in range(square):
      pos = row * square
      code = message[pos:pos + square]
      rows.append(code)

      print("The grid:n".format("n".join(rows)))

      # Encode the message
      coded_msg = ""
      for col in range(square):
      for row in range(square):
      # The last column of the last row will throw an out of range error, so handle that
      if col < len(rows[row]):
      coded_msg += rows[row][col]
      coded_msg += " "

      return coded_msg.rstrip()


      def decode(message):
      square = math.sqrt(len(message))
      col_count = math.ceil(square)
      row_count = math.ceil(len(message) / col_count)

      cols = message.split(" ")

      decoded_msg = ""
      for row in range(row_count):
      for col in cols:
      if row < len(col):
      decoded_msg += col[row]

      return decoded_msg


      if __name__ == "__main__":

      print("Gimme a message:")
      in_message = input()

      coded_message = encode(in_message)
      print("--nSquare message:n".format(coded_message))
      decoded_message = decode(coded_message)
      #print("--nDecoded message:n".format(decoded_message))

      print("--ninput: noutput: ".format(in_message, decoded_message))






      share|improve this question













      I am doing some python practice and wrote a square code encoder/decoder. As described in drill #4 of Programming Practice Problems, the characters of a message are written left-to-right on a square grid, and each line of the encoded message is read by going top to bottom.



      I'd like some feedback on what I wrote to see if there is anything I could have done better:



      import math


      def encode(message):
      message = message.replace(" ", "")
      square = math.ceil(math.sqrt(len(message)))

      # Create the "grid"
      rows =
      for row in range(square):
      pos = row * square
      code = message[pos:pos + square]
      rows.append(code)

      print("The grid:n".format("n".join(rows)))

      # Encode the message
      coded_msg = ""
      for col in range(square):
      for row in range(square):
      # The last column of the last row will throw an out of range error, so handle that
      if col < len(rows[row]):
      coded_msg += rows[row][col]
      coded_msg += " "

      return coded_msg.rstrip()


      def decode(message):
      square = math.sqrt(len(message))
      col_count = math.ceil(square)
      row_count = math.ceil(len(message) / col_count)

      cols = message.split(" ")

      decoded_msg = ""
      for row in range(row_count):
      for col in cols:
      if row < len(col):
      decoded_msg += col[row]

      return decoded_msg


      if __name__ == "__main__":

      print("Gimme a message:")
      in_message = input()

      coded_message = encode(in_message)
      print("--nSquare message:n".format(coded_message))
      decoded_message = decode(coded_message)
      #print("--nDecoded message:n".format(decoded_message))

      print("--ninput: noutput: ".format(in_message, decoded_message))








      share|improve this question












      share|improve this question




      share|improve this question








      edited Apr 3 at 22:34









      200_success

      123k14142399




      123k14142399









      asked Apr 3 at 19:59









      Spencer

      1767




      1767




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          2
          down vote



          accepted










          In both the encoder and decoder, you append one character at a time to the resulting string using +=. That is a bad habit for performance: since Python strings are immutable, appending a character means allocating a new string, then copying the old contents of the string plus the suffix.




          These solutions can be vastly simplified using Pythonic iteration techniques.



          The first trick is to note that Python strings are sequences, and therefore support slicing using the s[i:j:k] operation to extract every kth character:




          The slice of s from i to j with step k is defined as the sequence of items with index x = i + n*k such that 0 <= n < (j-i)/k. In other words, the indices are i, i+k, i+2*k, i+3*k and so on, stopping when j is reached (but never including j). When k is positive, i and j are reduced to len(s) if they are greater. … If i or j are omitted or None, they become “end” values (which end depends on the sign of k).




          Secondly, whenever you see a pattern like:



          array = 
          for … in …:
          array.append(…)


          … then that is an indication that you might want to use either a list comprehension or a generator expression, to define the whole array in just one statement.



          In this case, you want to join a bunch of words using a space character as a delimiter. So, you need to write it as ' '.join(some generator expression producing the columns).



          import math

          def encode(plaintext):
          plaintext = plaintext.replace(" ", "")
          size = math.ceil(math.sqrt(len(plaintext)))
          return ' '.join(plaintext[i::size] for i in range(size))



          To implement the decoder, you don't need to do any arithmetic. The trick here is to use itertools.zip_longest(*cols) to transpose the matrix and give you the rows.



          Again, I recommend using ''.join(…) with some generator expressions.



          from itertools import zip_longest

          def decode(ciphertext):
          cols = ciphertext.split(" ")
          return ''.join(''.join(c for c in row if c) for row in zip_longest(*cols))





          share|improve this answer























          • Wow, python is indeed beautiful! Fantastic answer, this teaches me a lot :)
            – Spencer
            Apr 4 at 16:43










          • Is there a reason you used "len(plaintext) ** 0.5" to get the square instead of math.sqrt(plaintext)? And sorry for the noob question but what exactly does the "*" in "*cols" do?
            – Spencer
            Apr 4 at 17:02










          • No reason for changing math.sqrt(); I've reverted it. The "splat" operator treats each element of the cols list as a separate parameter to zip_longest().
            – 200_success
            Apr 4 at 17:17

















          up vote
          2
          down vote













          Couple of pointers.



          In general it's good practice to avoid putting anything other than a call to another function (such as main()) in the if __name__ == "__main__" function, just to aid in ease of unit testing.



          Document strings for functions are also nice to have:



          def foo():
          '''This function does foo-all, always returns None'''
          pass


          A nice (ish) one liner for the decode function might be something like this:



          def encode(message):
          message = message.replace(" ", "")
          length = math.ceil(math.sqrt(len(message)))
          ''.join(message[i::length] i in range(length))


          Although I admit it needs a bit of refactoring as its a tad long for one line (EDIT adapted a very nice improvement from 200_success 's answer, which they explain well). It does demonstrate that you can skip building the grid though.






          share|improve this answer























          • Thanks Drgabble! Correct me if I'm wrong, but I thought it was "cleaner" to put any "testing" code in the main block so that the functions "encode" and "decode" can just be run from another module without worrying about extra junk at runtime?
            – Spencer
            Apr 4 at 16:40










          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191195%2fsquare-code-encode-and-decode%23new-answer', 'question_page');

          );

          Post as a guest






























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          2
          down vote



          accepted










          In both the encoder and decoder, you append one character at a time to the resulting string using +=. That is a bad habit for performance: since Python strings are immutable, appending a character means allocating a new string, then copying the old contents of the string plus the suffix.




          These solutions can be vastly simplified using Pythonic iteration techniques.



          The first trick is to note that Python strings are sequences, and therefore support slicing using the s[i:j:k] operation to extract every kth character:




          The slice of s from i to j with step k is defined as the sequence of items with index x = i + n*k such that 0 <= n < (j-i)/k. In other words, the indices are i, i+k, i+2*k, i+3*k and so on, stopping when j is reached (but never including j). When k is positive, i and j are reduced to len(s) if they are greater. … If i or j are omitted or None, they become “end” values (which end depends on the sign of k).




          Secondly, whenever you see a pattern like:



          array = 
          for … in …:
          array.append(…)


          … then that is an indication that you might want to use either a list comprehension or a generator expression, to define the whole array in just one statement.



          In this case, you want to join a bunch of words using a space character as a delimiter. So, you need to write it as ' '.join(some generator expression producing the columns).



          import math

          def encode(plaintext):
          plaintext = plaintext.replace(" ", "")
          size = math.ceil(math.sqrt(len(plaintext)))
          return ' '.join(plaintext[i::size] for i in range(size))



          To implement the decoder, you don't need to do any arithmetic. The trick here is to use itertools.zip_longest(*cols) to transpose the matrix and give you the rows.



          Again, I recommend using ''.join(…) with some generator expressions.



          from itertools import zip_longest

          def decode(ciphertext):
          cols = ciphertext.split(" ")
          return ''.join(''.join(c for c in row if c) for row in zip_longest(*cols))





          share|improve this answer























          • Wow, python is indeed beautiful! Fantastic answer, this teaches me a lot :)
            – Spencer
            Apr 4 at 16:43










          • Is there a reason you used "len(plaintext) ** 0.5" to get the square instead of math.sqrt(plaintext)? And sorry for the noob question but what exactly does the "*" in "*cols" do?
            – Spencer
            Apr 4 at 17:02










          • No reason for changing math.sqrt(); I've reverted it. The "splat" operator treats each element of the cols list as a separate parameter to zip_longest().
            – 200_success
            Apr 4 at 17:17














          up vote
          2
          down vote



          accepted










          In both the encoder and decoder, you append one character at a time to the resulting string using +=. That is a bad habit for performance: since Python strings are immutable, appending a character means allocating a new string, then copying the old contents of the string plus the suffix.




          These solutions can be vastly simplified using Pythonic iteration techniques.



          The first trick is to note that Python strings are sequences, and therefore support slicing using the s[i:j:k] operation to extract every kth character:




          The slice of s from i to j with step k is defined as the sequence of items with index x = i + n*k such that 0 <= n < (j-i)/k. In other words, the indices are i, i+k, i+2*k, i+3*k and so on, stopping when j is reached (but never including j). When k is positive, i and j are reduced to len(s) if they are greater. … If i or j are omitted or None, they become “end” values (which end depends on the sign of k).




          Secondly, whenever you see a pattern like:



          array = 
          for … in …:
          array.append(…)


          … then that is an indication that you might want to use either a list comprehension or a generator expression, to define the whole array in just one statement.



          In this case, you want to join a bunch of words using a space character as a delimiter. So, you need to write it as ' '.join(some generator expression producing the columns).



          import math

          def encode(plaintext):
          plaintext = plaintext.replace(" ", "")
          size = math.ceil(math.sqrt(len(plaintext)))
          return ' '.join(plaintext[i::size] for i in range(size))



          To implement the decoder, you don't need to do any arithmetic. The trick here is to use itertools.zip_longest(*cols) to transpose the matrix and give you the rows.



          Again, I recommend using ''.join(…) with some generator expressions.



          from itertools import zip_longest

          def decode(ciphertext):
          cols = ciphertext.split(" ")
          return ''.join(''.join(c for c in row if c) for row in zip_longest(*cols))





          share|improve this answer























          • Wow, python is indeed beautiful! Fantastic answer, this teaches me a lot :)
            – Spencer
            Apr 4 at 16:43










          • Is there a reason you used "len(plaintext) ** 0.5" to get the square instead of math.sqrt(plaintext)? And sorry for the noob question but what exactly does the "*" in "*cols" do?
            – Spencer
            Apr 4 at 17:02










          • No reason for changing math.sqrt(); I've reverted it. The "splat" operator treats each element of the cols list as a separate parameter to zip_longest().
            – 200_success
            Apr 4 at 17:17












          up vote
          2
          down vote



          accepted







          up vote
          2
          down vote



          accepted






          In both the encoder and decoder, you append one character at a time to the resulting string using +=. That is a bad habit for performance: since Python strings are immutable, appending a character means allocating a new string, then copying the old contents of the string plus the suffix.




          These solutions can be vastly simplified using Pythonic iteration techniques.



          The first trick is to note that Python strings are sequences, and therefore support slicing using the s[i:j:k] operation to extract every kth character:




          The slice of s from i to j with step k is defined as the sequence of items with index x = i + n*k such that 0 <= n < (j-i)/k. In other words, the indices are i, i+k, i+2*k, i+3*k and so on, stopping when j is reached (but never including j). When k is positive, i and j are reduced to len(s) if they are greater. … If i or j are omitted or None, they become “end” values (which end depends on the sign of k).




          Secondly, whenever you see a pattern like:



          array = 
          for … in …:
          array.append(…)


          … then that is an indication that you might want to use either a list comprehension or a generator expression, to define the whole array in just one statement.



          In this case, you want to join a bunch of words using a space character as a delimiter. So, you need to write it as ' '.join(some generator expression producing the columns).



          import math

          def encode(plaintext):
          plaintext = plaintext.replace(" ", "")
          size = math.ceil(math.sqrt(len(plaintext)))
          return ' '.join(plaintext[i::size] for i in range(size))



          To implement the decoder, you don't need to do any arithmetic. The trick here is to use itertools.zip_longest(*cols) to transpose the matrix and give you the rows.



          Again, I recommend using ''.join(…) with some generator expressions.



          from itertools import zip_longest

          def decode(ciphertext):
          cols = ciphertext.split(" ")
          return ''.join(''.join(c for c in row if c) for row in zip_longest(*cols))





          share|improve this answer















          In both the encoder and decoder, you append one character at a time to the resulting string using +=. That is a bad habit for performance: since Python strings are immutable, appending a character means allocating a new string, then copying the old contents of the string plus the suffix.




          These solutions can be vastly simplified using Pythonic iteration techniques.



          The first trick is to note that Python strings are sequences, and therefore support slicing using the s[i:j:k] operation to extract every kth character:




          The slice of s from i to j with step k is defined as the sequence of items with index x = i + n*k such that 0 <= n < (j-i)/k. In other words, the indices are i, i+k, i+2*k, i+3*k and so on, stopping when j is reached (but never including j). When k is positive, i and j are reduced to len(s) if they are greater. … If i or j are omitted or None, they become “end” values (which end depends on the sign of k).




          Secondly, whenever you see a pattern like:



          array = 
          for … in …:
          array.append(…)


          … then that is an indication that you might want to use either a list comprehension or a generator expression, to define the whole array in just one statement.



          In this case, you want to join a bunch of words using a space character as a delimiter. So, you need to write it as ' '.join(some generator expression producing the columns).



          import math

          def encode(plaintext):
          plaintext = plaintext.replace(" ", "")
          size = math.ceil(math.sqrt(len(plaintext)))
          return ' '.join(plaintext[i::size] for i in range(size))



          To implement the decoder, you don't need to do any arithmetic. The trick here is to use itertools.zip_longest(*cols) to transpose the matrix and give you the rows.



          Again, I recommend using ''.join(…) with some generator expressions.



          from itertools import zip_longest

          def decode(ciphertext):
          cols = ciphertext.split(" ")
          return ''.join(''.join(c for c in row if c) for row in zip_longest(*cols))






          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited Apr 4 at 17:14


























          answered Apr 4 at 6:16









          200_success

          123k14142399




          123k14142399











          • Wow, python is indeed beautiful! Fantastic answer, this teaches me a lot :)
            – Spencer
            Apr 4 at 16:43










          • Is there a reason you used "len(plaintext) ** 0.5" to get the square instead of math.sqrt(plaintext)? And sorry for the noob question but what exactly does the "*" in "*cols" do?
            – Spencer
            Apr 4 at 17:02










          • No reason for changing math.sqrt(); I've reverted it. The "splat" operator treats each element of the cols list as a separate parameter to zip_longest().
            – 200_success
            Apr 4 at 17:17
















          • Wow, python is indeed beautiful! Fantastic answer, this teaches me a lot :)
            – Spencer
            Apr 4 at 16:43










          • Is there a reason you used "len(plaintext) ** 0.5" to get the square instead of math.sqrt(plaintext)? And sorry for the noob question but what exactly does the "*" in "*cols" do?
            – Spencer
            Apr 4 at 17:02










          • No reason for changing math.sqrt(); I've reverted it. The "splat" operator treats each element of the cols list as a separate parameter to zip_longest().
            – 200_success
            Apr 4 at 17:17















          Wow, python is indeed beautiful! Fantastic answer, this teaches me a lot :)
          – Spencer
          Apr 4 at 16:43




          Wow, python is indeed beautiful! Fantastic answer, this teaches me a lot :)
          – Spencer
          Apr 4 at 16:43












          Is there a reason you used "len(plaintext) ** 0.5" to get the square instead of math.sqrt(plaintext)? And sorry for the noob question but what exactly does the "*" in "*cols" do?
          – Spencer
          Apr 4 at 17:02




          Is there a reason you used "len(plaintext) ** 0.5" to get the square instead of math.sqrt(plaintext)? And sorry for the noob question but what exactly does the "*" in "*cols" do?
          – Spencer
          Apr 4 at 17:02












          No reason for changing math.sqrt(); I've reverted it. The "splat" operator treats each element of the cols list as a separate parameter to zip_longest().
          – 200_success
          Apr 4 at 17:17




          No reason for changing math.sqrt(); I've reverted it. The "splat" operator treats each element of the cols list as a separate parameter to zip_longest().
          – 200_success
          Apr 4 at 17:17












          up vote
          2
          down vote













          Couple of pointers.



          In general it's good practice to avoid putting anything other than a call to another function (such as main()) in the if __name__ == "__main__" function, just to aid in ease of unit testing.



          Document strings for functions are also nice to have:



          def foo():
          '''This function does foo-all, always returns None'''
          pass


          A nice (ish) one liner for the decode function might be something like this:



          def encode(message):
          message = message.replace(" ", "")
          length = math.ceil(math.sqrt(len(message)))
          ''.join(message[i::length] i in range(length))


          Although I admit it needs a bit of refactoring as its a tad long for one line (EDIT adapted a very nice improvement from 200_success 's answer, which they explain well). It does demonstrate that you can skip building the grid though.






          share|improve this answer























          • Thanks Drgabble! Correct me if I'm wrong, but I thought it was "cleaner" to put any "testing" code in the main block so that the functions "encode" and "decode" can just be run from another module without worrying about extra junk at runtime?
            – Spencer
            Apr 4 at 16:40














          up vote
          2
          down vote













          Couple of pointers.



          In general it's good practice to avoid putting anything other than a call to another function (such as main()) in the if __name__ == "__main__" function, just to aid in ease of unit testing.



          Document strings for functions are also nice to have:



          def foo():
          '''This function does foo-all, always returns None'''
          pass


          A nice (ish) one liner for the decode function might be something like this:



          def encode(message):
          message = message.replace(" ", "")
          length = math.ceil(math.sqrt(len(message)))
          ''.join(message[i::length] i in range(length))


          Although I admit it needs a bit of refactoring as its a tad long for one line (EDIT adapted a very nice improvement from 200_success 's answer, which they explain well). It does demonstrate that you can skip building the grid though.






          share|improve this answer























          • Thanks Drgabble! Correct me if I'm wrong, but I thought it was "cleaner" to put any "testing" code in the main block so that the functions "encode" and "decode" can just be run from another module without worrying about extra junk at runtime?
            – Spencer
            Apr 4 at 16:40












          up vote
          2
          down vote










          up vote
          2
          down vote









          Couple of pointers.



          In general it's good practice to avoid putting anything other than a call to another function (such as main()) in the if __name__ == "__main__" function, just to aid in ease of unit testing.



          Document strings for functions are also nice to have:



          def foo():
          '''This function does foo-all, always returns None'''
          pass


          A nice (ish) one liner for the decode function might be something like this:



          def encode(message):
          message = message.replace(" ", "")
          length = math.ceil(math.sqrt(len(message)))
          ''.join(message[i::length] i in range(length))


          Although I admit it needs a bit of refactoring as its a tad long for one line (EDIT adapted a very nice improvement from 200_success 's answer, which they explain well). It does demonstrate that you can skip building the grid though.






          share|improve this answer















          Couple of pointers.



          In general it's good practice to avoid putting anything other than a call to another function (such as main()) in the if __name__ == "__main__" function, just to aid in ease of unit testing.



          Document strings for functions are also nice to have:



          def foo():
          '''This function does foo-all, always returns None'''
          pass


          A nice (ish) one liner for the decode function might be something like this:



          def encode(message):
          message = message.replace(" ", "")
          length = math.ceil(math.sqrt(len(message)))
          ''.join(message[i::length] i in range(length))


          Although I admit it needs a bit of refactoring as its a tad long for one line (EDIT adapted a very nice improvement from 200_success 's answer, which they explain well). It does demonstrate that you can skip building the grid though.







          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited Apr 4 at 12:12


























          answered Apr 3 at 23:14









          Drgabble

          1214




          1214











          • Thanks Drgabble! Correct me if I'm wrong, but I thought it was "cleaner" to put any "testing" code in the main block so that the functions "encode" and "decode" can just be run from another module without worrying about extra junk at runtime?
            – Spencer
            Apr 4 at 16:40
















          • Thanks Drgabble! Correct me if I'm wrong, but I thought it was "cleaner" to put any "testing" code in the main block so that the functions "encode" and "decode" can just be run from another module without worrying about extra junk at runtime?
            – Spencer
            Apr 4 at 16:40















          Thanks Drgabble! Correct me if I'm wrong, but I thought it was "cleaner" to put any "testing" code in the main block so that the functions "encode" and "decode" can just be run from another module without worrying about extra junk at runtime?
          – Spencer
          Apr 4 at 16:40




          Thanks Drgabble! Correct me if I'm wrong, but I thought it was "cleaner" to put any "testing" code in the main block so that the functions "encode" and "decode" can just be run from another module without worrying about extra junk at runtime?
          – Spencer
          Apr 4 at 16:40












           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191195%2fsquare-code-encode-and-decode%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Chat program with C++ and SFML

          Function to Return a JSON Like Objects Using VBA Collections and Arrays

          Will my employers contract hold up in court?