Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reverse words in a string, except punctuation

Tags:

c#

algorithm

Given a string

"hello there, compiler."

how does one reverse every word, except for the punctuation. So after completion this will be printed:

"olleh ereht, relipmoc." 

instead of "olleh ,ereht .relipmoc"

My code (that ignores punctuation):

 static string ReverseString(string s)
 {
     StringBuilder sb = new StringBuilder();
     string[] words = s.Split(' ');

     foreach (var word in words)
     {
         for (int i = word.Length - 1; i >= 0; i--)
         {
             sb.Append(word[i]);
         }

         sb.Append(" ");
     }

     return sb.ToString();
 }
like image 964
Kevin Malan Avatar asked Jul 13 '17 11:07

Kevin Malan


2 Answers

I suggest Split (trick: not on spaces only, but on non-word symbols - space, comma, dot etc.), modification and final Concat:

  using using System.Text.RegularExpressions;

  ...

  string source = @"hello there, compiler.";

  string result = string.Concat(Regex
    .Split(source, @"(\W+)") // split on not word letter, separator preserved
    .Select(letter => letter.Length > 0 && char.IsLetter(letter[0]) 
       ? string.Concat(letter.Reverse()) // reverse letter
       : letter));                       // keep separator intact 

  Console.Write(result);

Outcome:

  olleh ereht, relipmoc.
like image 196
Dmitry Bychenko Avatar answered Oct 21 '22 12:10

Dmitry Bychenko


Here is a solution based on the one you had originally. Simply check if the first character in the reverse word is punctuation and if it is keep it until the word is reversed then add it back. Not the most elegant solution, but it works

static string ReverseString(string s)
    {
        var sb = new StringBuilder();
        var words = s.Split(' ');

        foreach (var word in words)
        {
            var toAdd = new char();
            for (var i = word.Length -1; i >= 0; i--)
            {
                if (char.IsPunctuation(word[i]))
                {
                    toAdd = word[i];
                }
                else
                {
                    sb.Append(word[i]);
                }
            }
            if (toAdd != new char())
            {
                sb.Append(toAdd);
            }

            sb.Append(" ");
        }

        return sb.ToString();
    }

Edit: And a slightly more compact version of the above code:

static string ReverseString(string s)
    {
        var sb = new StringBuilder();

        foreach (var s1 in s.Split(' '))
        {
            var rev = s1.Reverse().ToList();
            char punct;
            if (char.IsPunctuation(punct = rev.First()))
            {
                rev.RemoveAt(0);
                rev.Add(punct);
            }
            rev.Add(' ');
            sb.Append(rev.ToArray());
        }
        return sb.ToString();
    }
like image 1
DeadlyEmbrace Avatar answered Oct 21 '22 12:10

DeadlyEmbrace