String reversing x times












1














Inspired by CodeWars




We have a string s



Let's say you start with this: "String"

The first thing you do is reverse it: "gnirtS"

Then you will take the string from the 1st position and reverse it
again: "gStrin"

Then you will take the string from the 2nd position and reverse it
again: "gSnirt"

Then you will take the string from the 3rd position and reverse it
again: "gSntri"



Continue this pattern until you have done every single position, and
then you will return the string you have created. For this particular
string, you would return: "gSntir"



The Task:

In this kata, we also have a number x

take the above reversal function, and apply it to the string x times.

Return the result of the string after applying the reversal function to it x times.



Note:

String lengths may exceed 2 million and x may exceed a billion.
Be ready to optimize.




My solution works but times out and I am having trouble optimizing much further. The code contains a lot of useful comments but here is a summary of what I have attempted to do.



Cycle Length Calculation

Because the above algorithm generates cycles, we can calculate a strings cycle length and perform x % cycleLength to determine exactly how many iterations we must perform to get our end result, instead of having to calculate all the duplicate cycles. More on cycle lengths can be fouind here and here.



This method is better than nothing but can still get quite demanding on high cycle lengths. Potentially there is a better way of calculating the cycle length without so many iterations?



public final class XIterations {
public static String xReverse(String s, long x) {
// Using the cycle length and modular arithmetic,
// We can find the exact number of reverse operations we will need to perform.
// This way we will only perform operations we need to complete.
long iterationsRequired = x % calculateCycleLength(s.length());

// TODO: There may exist an algorithm that allows a linear transformation given x
while (iterationsRequired > 0) {
s = reverse(s);
iterationsRequired--;
}

return s;
}

// The xReverse algorithm produces cycles and therefore duplicates.
// This helper method determines the length of the cycle using the number of characters a string contains.
// More detail on the algorithm can be found at:
// https://oeis.org/A003558
// https://oeis.org/A216066
// TODO: There may exist an algorithm that requires less iterations to find the cycle length
private static int calculateCycleLength(int n) {
// Cache these so we only calculate them once.
final int a = 2 * n + 1;
final int b = 2 * n;

int cycleLength = 1;
while (true) {
double c = Math.pow(2, cycleLength);
if (c % a == 1 || c % a == b) {
return cycleLength;
}
cycleLength++;
}
}

public static String reverse(String s) {
StringBuilder sb = new StringBuilder();
int front = 0;
int back = s.length() - 1;
// Does not account for odd length strings. Will not add the middle character.
while (front < back) {
sb.append(s.charAt(back--));
sb.append(s.charAt(front++));
}

// Account for odd length strings. Add the middle character that was never added by loop.
if (front == back) {
sb.append(s.charAt(front));
}
return sb.toString();
}
}


I am mostly interested in optimization tips but of course any feedback is welcome.










share|improve this question





























    1














    Inspired by CodeWars




    We have a string s



    Let's say you start with this: "String"

    The first thing you do is reverse it: "gnirtS"

    Then you will take the string from the 1st position and reverse it
    again: "gStrin"

    Then you will take the string from the 2nd position and reverse it
    again: "gSnirt"

    Then you will take the string from the 3rd position and reverse it
    again: "gSntri"



    Continue this pattern until you have done every single position, and
    then you will return the string you have created. For this particular
    string, you would return: "gSntir"



    The Task:

    In this kata, we also have a number x

    take the above reversal function, and apply it to the string x times.

    Return the result of the string after applying the reversal function to it x times.



    Note:

    String lengths may exceed 2 million and x may exceed a billion.
    Be ready to optimize.




    My solution works but times out and I am having trouble optimizing much further. The code contains a lot of useful comments but here is a summary of what I have attempted to do.



    Cycle Length Calculation

    Because the above algorithm generates cycles, we can calculate a strings cycle length and perform x % cycleLength to determine exactly how many iterations we must perform to get our end result, instead of having to calculate all the duplicate cycles. More on cycle lengths can be fouind here and here.



    This method is better than nothing but can still get quite demanding on high cycle lengths. Potentially there is a better way of calculating the cycle length without so many iterations?



    public final class XIterations {
    public static String xReverse(String s, long x) {
    // Using the cycle length and modular arithmetic,
    // We can find the exact number of reverse operations we will need to perform.
    // This way we will only perform operations we need to complete.
    long iterationsRequired = x % calculateCycleLength(s.length());

    // TODO: There may exist an algorithm that allows a linear transformation given x
    while (iterationsRequired > 0) {
    s = reverse(s);
    iterationsRequired--;
    }

    return s;
    }

    // The xReverse algorithm produces cycles and therefore duplicates.
    // This helper method determines the length of the cycle using the number of characters a string contains.
    // More detail on the algorithm can be found at:
    // https://oeis.org/A003558
    // https://oeis.org/A216066
    // TODO: There may exist an algorithm that requires less iterations to find the cycle length
    private static int calculateCycleLength(int n) {
    // Cache these so we only calculate them once.
    final int a = 2 * n + 1;
    final int b = 2 * n;

    int cycleLength = 1;
    while (true) {
    double c = Math.pow(2, cycleLength);
    if (c % a == 1 || c % a == b) {
    return cycleLength;
    }
    cycleLength++;
    }
    }

    public static String reverse(String s) {
    StringBuilder sb = new StringBuilder();
    int front = 0;
    int back = s.length() - 1;
    // Does not account for odd length strings. Will not add the middle character.
    while (front < back) {
    sb.append(s.charAt(back--));
    sb.append(s.charAt(front++));
    }

    // Account for odd length strings. Add the middle character that was never added by loop.
    if (front == back) {
    sb.append(s.charAt(front));
    }
    return sb.toString();
    }
    }


    I am mostly interested in optimization tips but of course any feedback is welcome.










    share|improve this question



























      1












      1








      1







      Inspired by CodeWars




      We have a string s



      Let's say you start with this: "String"

      The first thing you do is reverse it: "gnirtS"

      Then you will take the string from the 1st position and reverse it
      again: "gStrin"

      Then you will take the string from the 2nd position and reverse it
      again: "gSnirt"

      Then you will take the string from the 3rd position and reverse it
      again: "gSntri"



      Continue this pattern until you have done every single position, and
      then you will return the string you have created. For this particular
      string, you would return: "gSntir"



      The Task:

      In this kata, we also have a number x

      take the above reversal function, and apply it to the string x times.

      Return the result of the string after applying the reversal function to it x times.



      Note:

      String lengths may exceed 2 million and x may exceed a billion.
      Be ready to optimize.




      My solution works but times out and I am having trouble optimizing much further. The code contains a lot of useful comments but here is a summary of what I have attempted to do.



      Cycle Length Calculation

      Because the above algorithm generates cycles, we can calculate a strings cycle length and perform x % cycleLength to determine exactly how many iterations we must perform to get our end result, instead of having to calculate all the duplicate cycles. More on cycle lengths can be fouind here and here.



      This method is better than nothing but can still get quite demanding on high cycle lengths. Potentially there is a better way of calculating the cycle length without so many iterations?



      public final class XIterations {
      public static String xReverse(String s, long x) {
      // Using the cycle length and modular arithmetic,
      // We can find the exact number of reverse operations we will need to perform.
      // This way we will only perform operations we need to complete.
      long iterationsRequired = x % calculateCycleLength(s.length());

      // TODO: There may exist an algorithm that allows a linear transformation given x
      while (iterationsRequired > 0) {
      s = reverse(s);
      iterationsRequired--;
      }

      return s;
      }

      // The xReverse algorithm produces cycles and therefore duplicates.
      // This helper method determines the length of the cycle using the number of characters a string contains.
      // More detail on the algorithm can be found at:
      // https://oeis.org/A003558
      // https://oeis.org/A216066
      // TODO: There may exist an algorithm that requires less iterations to find the cycle length
      private static int calculateCycleLength(int n) {
      // Cache these so we only calculate them once.
      final int a = 2 * n + 1;
      final int b = 2 * n;

      int cycleLength = 1;
      while (true) {
      double c = Math.pow(2, cycleLength);
      if (c % a == 1 || c % a == b) {
      return cycleLength;
      }
      cycleLength++;
      }
      }

      public static String reverse(String s) {
      StringBuilder sb = new StringBuilder();
      int front = 0;
      int back = s.length() - 1;
      // Does not account for odd length strings. Will not add the middle character.
      while (front < back) {
      sb.append(s.charAt(back--));
      sb.append(s.charAt(front++));
      }

      // Account for odd length strings. Add the middle character that was never added by loop.
      if (front == back) {
      sb.append(s.charAt(front));
      }
      return sb.toString();
      }
      }


      I am mostly interested in optimization tips but of course any feedback is welcome.










      share|improve this question















      Inspired by CodeWars




      We have a string s



      Let's say you start with this: "String"

      The first thing you do is reverse it: "gnirtS"

      Then you will take the string from the 1st position and reverse it
      again: "gStrin"

      Then you will take the string from the 2nd position and reverse it
      again: "gSnirt"

      Then you will take the string from the 3rd position and reverse it
      again: "gSntri"



      Continue this pattern until you have done every single position, and
      then you will return the string you have created. For this particular
      string, you would return: "gSntir"



      The Task:

      In this kata, we also have a number x

      take the above reversal function, and apply it to the string x times.

      Return the result of the string after applying the reversal function to it x times.



      Note:

      String lengths may exceed 2 million and x may exceed a billion.
      Be ready to optimize.




      My solution works but times out and I am having trouble optimizing much further. The code contains a lot of useful comments but here is a summary of what I have attempted to do.



      Cycle Length Calculation

      Because the above algorithm generates cycles, we can calculate a strings cycle length and perform x % cycleLength to determine exactly how many iterations we must perform to get our end result, instead of having to calculate all the duplicate cycles. More on cycle lengths can be fouind here and here.



      This method is better than nothing but can still get quite demanding on high cycle lengths. Potentially there is a better way of calculating the cycle length without so many iterations?



      public final class XIterations {
      public static String xReverse(String s, long x) {
      // Using the cycle length and modular arithmetic,
      // We can find the exact number of reverse operations we will need to perform.
      // This way we will only perform operations we need to complete.
      long iterationsRequired = x % calculateCycleLength(s.length());

      // TODO: There may exist an algorithm that allows a linear transformation given x
      while (iterationsRequired > 0) {
      s = reverse(s);
      iterationsRequired--;
      }

      return s;
      }

      // The xReverse algorithm produces cycles and therefore duplicates.
      // This helper method determines the length of the cycle using the number of characters a string contains.
      // More detail on the algorithm can be found at:
      // https://oeis.org/A003558
      // https://oeis.org/A216066
      // TODO: There may exist an algorithm that requires less iterations to find the cycle length
      private static int calculateCycleLength(int n) {
      // Cache these so we only calculate them once.
      final int a = 2 * n + 1;
      final int b = 2 * n;

      int cycleLength = 1;
      while (true) {
      double c = Math.pow(2, cycleLength);
      if (c % a == 1 || c % a == b) {
      return cycleLength;
      }
      cycleLength++;
      }
      }

      public static String reverse(String s) {
      StringBuilder sb = new StringBuilder();
      int front = 0;
      int back = s.length() - 1;
      // Does not account for odd length strings. Will not add the middle character.
      while (front < back) {
      sb.append(s.charAt(back--));
      sb.append(s.charAt(front++));
      }

      // Account for odd length strings. Add the middle character that was never added by loop.
      if (front == back) {
      sb.append(s.charAt(front));
      }
      return sb.toString();
      }
      }


      I am mostly interested in optimization tips but of course any feedback is welcome.







      java performance strings programming-challenge






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 35 mins ago









      200_success

      128k15150412




      128k15150412










      asked 40 mins ago









      JSextonn

      411211




      411211



























          active

          oldest

          votes











          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',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          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%2f210529%2fstring-reversing-x-times%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210529%2fstring-reversing-x-times%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Quarter-circle Tiles

          build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

          Mont Emei