El megafriki de Pablo Alvarez Doval, nos envió una felicitación navideña códificada con caractéres hexadecimales. Cualquier persona normal hubiese pegado la felicitación en un editor de texto un poco potente y hubiese visto lo que decía. Pero el amigo Octavio Hernandez abrió la caja de Pandora: mando un método extensor para la clase String que descodificaba el mensaje.
Yo no he podido menos que recoger el guante e implementar mi propia solución al problema. He tratado de hacer algo original ,no eficiente, de hecho la solución de Octavio (que espero que publique en su blog) es infinitamente más eficiente. Yo he decidido usar paralelización, usando Microsoft Parallel Extensions, siguiendo mi proposito de este año de actualizar mis conocimientos de programación concurrente.
Dada la cadena en hexadecimal del mensaje, se hace evidente que la conversión de cada uno de los caracteres desde su represantación hexadecimal a un valor de tipo char es un operación atómica e independiente para cada caracter. Sin duda es una buena ocasión de usar programación concurrente (aunque a nadie se le debería ocurrir usar esto en un escenario real, el coste de la paralelización anula cualquier ventaja de rendimiento, en casos donde cada operación independiente tiene un coste mínimo como es el caso).
1 using System;
2 using System.Diagnostics;
3 using System.Threading;
4
5 namespace ParallelDecode
6 {
7 class Program
8 {
9 const string message =
10 «%46%65%6C%69%63%65%73%20%46%69%65%73» +
11 «%74%61%73%2C%20%63%61%63%68%6F%20%66» +
12 «%72%69%6B%69%21%20%41%68%6F%72%61%2C» +
13 «%20%64%65%6A%61%74%65%20%64%65%20%74» +
14 «%6F%6E%74%65%72%69%61%73%20%79%20%76» +
15 «%65%74%65%20%61%20%65%6D%62%6F%72%72» +
16 «%61%63%68%61%72%74%65%20%75%6E%20%70» +
17 «%6F%71%75%69%6E%21%21%20%4B%65%65%70» +
18 «%20%52%6F%63%6B%69%6E%27%21%21»;
19
20 static void Main(string[] args)
21 {
22 Stopwatch sw = new Stopwatch();
23 sw.Start();
24
25 string[] splitedMessage = message.Split(‘%’);
26
27 char[] result = new char[splitedMessage.Length – 1];
28
29 Parallel.For(0, result.Length, i =>
30 {
31 result[i] = (char)(int.Parse(splitedMessage[i + 1], System.Globalization.NumberStyles.AllowHexSpecifier));
32 }
33 );
34
35 sw.Stop();
36
37 Console.WriteLine(result);
38 Console.WriteLine(«Tiempo de proceso: {0} ms.», sw.ElapsedMilliseconds);
39
40 Console.ReadKey();
41 }
42 }
43 }
En un post reciente me preguntaba si las abstracciones que se están construyendo serían lo suficientemente simples para facilitar la programación concurrente al comuún de los mortales… parece que sí, pues el código no puede ser más simple y desde luego es muchísimo más simple usar Parallel Extensions que la que hacer lo mismo usando hilos. La clase Parallel nos propociona mecanismos sumamente potentes y simples a la hora de añadir paralelización a porciones iterativas de nuestro código sin esfuerzo alguno.
¿Alguien más se anima a publicar otras soluciones diferentes al problema? ¿Quizás con LINQ o PLINQ? ¿Alguien con F#? ¿Alguien con T-SQL?…