Invertir una cadena [C#]

Durante la plática de reclutamiento para Microsoft que hubo hace unos días en la ESCOM hicieron una prueba a los asistentes, la prueba consistía en escribir el código de dos funciones:
Una capaz de invertir una cadena, es decir, pasar de "this is a string" a "gnirts a si siht"
Otra muy similar pero solo debía invertir las palabras, pasando de "this is a string" a "siht si gnirts"
Basándonos en un prototipo de función más o menos así:
char* reverse(const char* str)

El lenguaje a usar era cualquiera con el que te sintieras cómodo, C#, C, Java... en fin. La idea era que usaras la menor cantidad de herramientas provistas por el framework o por el lenguaje que escogiste (¡no se valía el .Reverse()!), es decir que todo lo hicieras "artesanalmente". Eso si, no recuerdo muy bien cuanto tiempo dieron para escribir.

Por suerte yo me había encontrado con un problema similar unos días antes, así que creo que no me fue tan mal en esta. Mi solución la propuse en dos lenguajes, C para la primera y (por cuestiones de tiempo) C# para la segunda. Ahora vengo acá a colocar mis soluciones un poco más pensadas y totalmente funcionales escritas en C#:

using System;
using System.Linq;
using System.Text;

namespace ReverseStringsMsft
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "this  is  a string";
            string res = Reverse(s);
            string resWord = ReverseWords(s);
            Console.WriteLine(s);
            Console.WriteLine(res);
            Console.WriteLine(resWord);
            Console.Read();
        }

        /// <summary>
        /// Invierte una cadena
        /// </summary>
        /// <param name="str">La cadena que será invertida</param>
        /// <returns>Una nueva instancia de String</returns>
        public static string Reverse(string str)
        {
            if (str == null)
                return null;
   // Convertir a un arreglo
            char[] cr = str.ToArray();
   // Llamamos a la funcion para toda la cadena
            Reverse(cr, 0, cr.Length - 1);
            return new string(cr);
        }

        /// <summary>
        /// Invierte las subcadenas (separadas por espacios) contenidas dentro de una cadena
        /// </summary>
        /// <param name="str">La cadena que será invertida</param>
        /// <returns>Una nueva instancia de String</returns>
        public static string ReverseWords(string str)
        {
            if (str == null)
                return null;
   // Convertir a un arreglo
            char[] cr = str.ToArray();
            int wordStart = 0;
            int end;
   // Recorremos la cadena para encontrar espacios
            for (int i = 0; i < cr.Length; i++)
            {
                char c = cr[i];
    // Por cada espacio o cada vez que lleguemos al final de la cadena
    // llamaremos a la funcion especialmente para la ubicacion de 
    // la palabra encontrada
                if (c == ' ' || i == cr.Length - 1)
                {
                    end = i - 1;
                    Reverse(cr, wordStart, end);
                    wordStart = i + 1;
                }
            }
            return new string(cr);
        }

        /// <summary>
        /// Cambia de posición los caracteres desde <paramref name="start"/> a
  /// <paramref name="end"/> hasta que todos estén invertidos
        /// </summary>
        /// <param name="str">El arreglo a ser invertido</param>
        /// <param name="start">Inicio</param>
        /// <param name="end">Final</param>
        private static void Reverse(char[] str, int start, int end)
        {
            for (; start < end; start++, end--)
            {
    // Cambiamos uno a uno los caracteres desde la posicion
    // inicial hasta la final, y aumentamos las variables para irlos 
    // intercambiando como deseamos
                char aux = str[start];
                str[start] = str[end];
                str[end] = aux;
            }
        }

    }
}


¡Saludos!
@fferegrino :)

2 comments:

  1. Por que hiciste en C#, no en el primero solo aplicas un
    public static string Reverse(string s){
    char[] arr = s.ToCharArray();
    Array.Reverse(arr);
    return new string(arr);
    }
    y en el segundo aplicas un Split a la cadena y mandas a llamar a Reverse por cada elemento en el array del Split.
    Se ve mucho mas elegante es mas eficiente y escribes menos.

    ReplyDelete
  2. Exacto, olvidé mencionarlo: La idea era usar la menor cantidad de funciones ya escritas o pertenecientes al framework. Lo que entregué para la prueba fue escrito en C, y es que el prototipo de la función que ellos nos dieron era algo como char* reverse(const char* str);

    Ese ToCharArray(); lo uso para hacer más transparente la implementación del método para el usuario final.

    ReplyDelete

¡Hey, gracias por tu comentario! No seas anónimo, inicia sesión para que te responda más fácilmente.