views:

277

answers:

7

I have been working on two methods that will Transpose and Untranspose a String respectively. The solutions that I have come up with both work to the best of my knowledge. I just want to know if I could have solved these problems in a simpler way. My code seems like it is too long for the task that is being performed. The first method, transpose(), will take a String as a parameter and transpose it. If "bridge" is entered, the output will be "bergid". Likewise, with the unTranspose() method, if the user enters "bergid", the output will be "bridge".

  public void transpose( String s )
  {
      String t = ""; 
      int end = s.length() - 1;


        for ( int i = 0; i < s.length()  / 2; i++ )
        {
            t += Character.toString( s.charAt( i ) ) + Character.toString( s.charAt( end ) );
            end--;
        }
        // Lenth of String is odd
        if ( s.length() % 2 == 1 )
        {
            // add character in middle of String to the end of the new String
            t+= Character.toString( s.charAt( s.length() / 2 ) );
        }

        System.out.println( t );
  }

    public void unTranspose( String s )
    {
    String t = ""; 

      // Length of String is odd
      if ( s.length() % 2 == 1 )
      {
      for ( int i = 0; i < s.length(); i+=2 )
      {
        t+= Character.toString( s.charAt( i ) );
      }

      for ( int i = s.length() - 2; i > 0; i -= 2 )
      {
        t += Character.toString( s.charAt( i ) );
      }

         System.out.println( t );
      }



   // Length of String is even
   else if ( s.length() % 2 == 0 )
   {
    for ( int i = 0; i < s.length() - 1; i+=2 )
    {
       t+= Character.toString( s.charAt( i ) );
    }

    for ( int i = s.length() - 1; i > 0; i -= 2 )
    {
        t+= Character.toString( s.charAt( i ) );
    }


    System.out.println( t );
}
   }

My code looks horrible. I'm still not used to formatting my code correctly. Please bear with me.

Thanks for your time


Definition

         transpose
         --------->
"123Xcba"            "1a2b3cX"
        <-----------
        untranspose
+1  A: 

Here is my response to this - The main issue I saw with your code is you creating Strings as temporary objects in multiple areas of the code - This makes it very inefficient as well as very slow. The other issue is that you want to externalize all you can from the loops. I have compiled it and run it and it works.

package com.rch.test;

public class Transposer
{
    public static String transpose(String s)
    {
        int length = s.length();
        int end = length - 1;

        StringBuilder t = new StringBuilder();
        for (int i = 0; i < length / 2; i++)
        {
            t.append(s.charAt(i));
            t.append(s.charAt(end));
            end--;
        }

        // Length of String is odd
        if (length % 2 == 1)
        {
            // add character in middle of String to the end of the new String
            t.append(s.charAt(length / 2));
        }
        return t.toString();
    }

    public static String unTranspose(String s)
    {
        int length = s.length();
        StringBuilder t = new StringBuilder();

        if (length % 2 == 1)
        {
            for (int i = 0; i < length; i += 2)
            {
                t.append(s.charAt(i));
            }

            for (int i = length - 2; i > 0; i -= 2)
            {
                t.append(s.charAt(i));
            }
        }
        else if (length % 2 == 0)
        {
            for (int i = 0; i < length - 1; i += 2)
            {
                t.append(s.charAt(i));
            }

            for (int i = length - 1; i > 0; i -= 2)
            {
                t.append(s.charAt(i));
            }
        }
        return t.toString();
    }

    public static void main(String[] args)
    {
        String testString = "bridge";
        String transposedString = Transposer.transpose(testString); 
        String finalString = Transposer.unTranspose(transposedString);

        System.out.println("1)" + testString);
        System.out.println("2)" + transposedString);
        System.out.println("3)" + finalString);
    }
}

Output : 1)bridge 2)bergid 3)bridge

Romain Hippeau
A: 

Hi, had a quick shot at doing your transpose method using a StringBuilder which usually makes these kind of operations simpler. This seems to work with your bridge example and also Strings of odd length.

public static void transpose( String s ) 
{
    StringBuilder sb = new StringBuilder(s);

    for( int i=1; i<sb.length(); i=i+2 ) {          
        sb.insert( i, sb.charAt( sb.length()-1 ) );         
        sb.deleteCharAt( sb.length()-1 );
    }

    System.out.println( sb.toString() );
}

Should give you enough ideas to implement the untranspose method yourself :+)

Binary Nerd
This is `O(N^2)` due to shifts due to `insert`. And the way `sb` is shrinking after each iteration makes it overly complicated to evaluate the condition of termination.
polygenelubricants
@polygenelubricants - yes, thanks for pointing out that an `insert` is actually quite inefficient. You made me did into the javadocs for that one. I'll admit my main aim was to see how few lines of code I could do it in :+)
Binary Nerd
A: 

Here is a method that does not require different behavior based upon whether the length of the string is even or odd.

public static String transpose(String in)
{
    StringBuilder out = new StringBuilder();
    for (int i=0; i<in.length(); ++i)
    {
        out.append(in.charAt(i));
        out.append(in.charAt(in.length() - i - 1));
    }
    return out.substring(0, in.length());
}

public static String untranspose(String in)
{
    StringBuilder out = new StringBuilder();
    for (int i=0; i<in.length(); i+=2)
    {
        out.append(in.charAt(i));
    }
    StringBuilder reversedSecondHalf = new StringBuilder();
    for (int i=1; i<in.length(); i+=2)
    {
        reversedSecondHalf.append(in.charAt(i));
    }
    out.append(reversedSecondHalf.reverse());
    return out.toString();
}
Matthew T. Staebler
Wow, after seeing so many good solutions, i feel terrible about my code :( Thanks for the different responses. I believe it helps to see different approaches to a problem.
Will
@Will, I would not worry too much about the elegance of your code. From my experience, I have found that I often waste too much time trying to improve the elegance of the code when all that is ultimately important is the functionality of the code. I would recommend that you focus your attention more on making solid tests for the code. If the code passes the tests, it is sufficient. The only problem that I see with what you wrote is the excessive use of String concatenations--which can be done more efficiently with something like StringBuilder.
Matthew T. Staebler
A: 

Well, I was able to simplify the transpose method a bit:

public static String transpose(String s)
{
   StringBuilder sb = new StringBuilder();
   int i = 0;
   int length = s.length() - 1;
   while(i < length - i)
   {
      sb.append(s.charAt(i)).append(s.charAt(length - i));
      i++;
   }
   if(i == length - i) sb.append(s.charAt(i));
   return sb.toString();
}

Update

Tried my luck with untranspose -

public static String untranspose(String s)
{
   StringBuilder sb1 = new StringBuilder();
   StringBuilder sb2 = new StringBuilder();
   int length = s.length();
   int iopp = (length % 2 == 0) ? length - 1 : length - 2;
   for(int i = 0; i < length; i += 2, iopp -= 2)
   {
      sb1.append(s.charAt(i));
      if(iopp >= 0) sb2.append(s.charAt(iopp));
   }
   return sb1.append(sb2).toString();
}
Phil
+2  A: 

This solution has a nice symmetry.

public static String transpose(String s) {
    StringBuilder sb = new StringBuilder();
    sb.setLength(s.length());
    for (int i = 0, j = s.length() - 1, x = 0; i <= j; ) {
        sb.setCharAt(x++, s.charAt(i++));
        if (i > j) break;
        sb.setCharAt(x++, s.charAt(j--));
    }
    return sb.toString();
}

public static String untranspose(String s) {
    StringBuilder sb = new StringBuilder();
    sb.setLength(s.length());
    for (int i = 0, j = s.length() - 1, x = 0; i <= j; ) {
        sb.setCharAt(i++, s.charAt(x++));
        if (i > j) break;
        sb.setCharAt(j--, s.charAt(x++));
    }
    return sb.toString();
}

This makes it obvious that the logic between the two methods are identical; the only difference is that:

  • In transpose, i and j are read indices, x is a write index
  • In untranspose, i and j are write indices, x is a read index (i.e. it's the other way around)

It's really quite simple:

  • i always goes from beginning to middle of string
  • j always goes from end to middle of string
  • x always goes from beginning to end of string
  • If the input is of odd length, inevitably i == j eventually
    • At that point you only need i, so break

Lalith came up with the first recursive solution; this one is essentially the same, with minor modification:

public static String transpose(String s) {
  int L = s.length();
  return (L < 2) ? s
    : s.substring(0, 1) + s.substring(L-1, L) + transpose(s.substring(1, L-1));
}

public static String untranspose(String s) {
  int L = s.length();
  return (L < 2) ? s
    : s.substring(0, 1) + untranspose(s.substring(2, L)) + s.substring(1, 2);
}
polygenelubricants
A: 

Here is another solution that shows the symmetry between transposing and untransposing.

public static String transpose(String in)
{
    int length = in.length();
    StringBuilder out = new StringBuilder(in);
    for (int pos=1; pos<length; pos+=2)
    {
        swapCharacters(out, length-1, pos);
    }
    return out.toString();
}

public static String untranspose(String in)
{
    int length = in.length();
    StringBuilder out = new StringBuilder(in);
    for (int pos=length-1-(length%2); pos>0; pos-=2)
    {
        swapCharacters(out, pos, length-1);
    }
    return out.toString();
}

private static void swapCharacters(StringBuilder string, int oldPos, int newPos)
{
    char c = string.charAt(oldPos);
    string.deleteCharAt(oldPos);
    string.insert(newPos, c);
}
Matthew T. Staebler
+2  A: 

Using Recursion

public static String transpose(String str) {

    if (str == null || str.length() == 1 || str.length() == 2) {
        return str;
    } else {
        return str.substring(0, 1) + str.substring(str.length() -1, str.length()) + transpose(str.substring(1, str.length() -1) );
    }
}

public static String untranspose(String str) {
    if (str == null || str.length() == 1 ||str.length() == 2) {
        return str;
    } else {
        return  str.substring(0, 1) + untranspose(str.substring(2, str.length())) + str.substring(1, 2);
    }
}
Lalith
+1! Very nice! And symmetric too!
polygenelubricants