Patrones semi-aleatorios en Small Basic

Hace algunas semanas me encontré por casualidad Microsoft Small Basic, una implementación del paradigma de programación para niños que utiliza una tortuga en pantalla a la cual se le dan órdenes tales como moverse hacia adelante o rotar una cantidad específica de grados.

Logo, otra implementación de este paradigma, fue la forma en la cual yo entré en el mundo de la programación allá por 1986, hace ya 24 años. Debido a esto encontrar Small Basic me llenó de gratos recuerdos y desde entonces he dedicado algunos de mis ratos libres a jugar de nuevo con este paradigma tan interesante y motivador, que me llevó a encontrar mi vocación hace tanto tiempo.

Una de las principales razones por las cuales la Tortuga es una de las mejores formas de introducir a los niños al mundo de la programación es que los resultados del código escrito se pueden ver en pantalla de forma rápida e inmediata y las permutaciones que se pueden hacer al código dan para horas de entretenimiento infantil. Adicionalmente, no es necesario aprender muchos conceptos teóricos de programación antes de obtener resultados agradables.

En una de estas sesiones de juego con la tortuga, me dí a la tarea de crear un algoritmo que me permitiera simular cierto grado aleatoriedad en el resultado visual, pero sin sacrificar la belleza del mismo. Para esto introduje niveles de aleatoriedad controlados dentro del marco de ciertas reglas. El resultado sigue siendo aleatorio (y sorpresivo), y por lo tanto cada uno de los patrones generados tiene una muy baja probabilidad de repetirse nuevamente; sin embargo, a pesar del aparente caos reinante en los patrones, estos muestran orden como un todo, lo cual los hace en su mayoría atractivos al ojo humano.

Algunos de los resultados del algoritmo se presentan a continuación:

 

Si desea ver más resultados, puede descargar Small Basic y utilizar el algoritmo para generarlos:

seed = Math.GetRandomNumber(24)
goal = seed * 15
maxSteps = Math.GetRandomNumber(48)
steps = Math.GetRandomNumber(maxSteps) + 1
For j = 1 To steps
  angles[j] = Math.GetRandomNumber(goal)
EndFor

distance = Math.GetRandomNumber(100)

Turtle.Speed = 10
GraphicsWindow.PenColor = GraphicsWindow.GetRandomColor()

For i = 1 To 50
  For j = 1 To steps
    angle1 = angles[j]
    angle2 = goal – angle1 
    Turtle.Turn(angle1)
    Turtle.Move(distance)
    Turtle.Turn(angle2)
    Turtle.Move(distance)
  EndFor
EndFor

Turtle.Hide()

TFS en Expression Blend 3

Para habilitar la integración entre Expression Blend 3 y Team Foundation Server, es necesario bajar e instalar un parche que se encuentra en la siguiente ubicación:
 
 
Después de la instalación Blend realizará el "check out" de los archivos de forma automática cuando estos son modificados, lo cual ahorra mucho tiempo al trabajar sobre archivos que están bajo control de versiones de código usando TFS.

Diálogo de creación de pruebas unitarias vacío

En estos días he estado modificando un proyecto bastante grande que hemos retomado después de casi un año de inactividad. Después de varios días llego el momento de crear la primera prueba unitaria (unit test) para las clases agregadas.
 
Para mi sorpresa, cuando abrí el cuadro de diálogo correspondiente este se desplegó vacío y no me daba ninguna opción.
 
Después de realizar una rápida búsqueda, descubrí que la causa era una pulga que se presentaba cuando uno de los proyectos no producían como salida un esamble (assembly, .dll), como es el caso de los proyectos de bases de datos y Silverlight.
 
En este caso el problema era un proyecto de base de datos (VSTS DBE GDR2).
 
Afortunadamente Microsoft ya había producido un parche para esta pulga, el cual puede ser descargado desde esta dirección:
 
 
Después de bajarlo e instalarlo la generación de pruebas volvió a funcionar adecuadamente.
 
 

Expression Blend: Habilitar la edición de controles

Estos días he desarollado algunos controles de WPF en librerías externas al proyecto principal, y en el proceso me dí cuenta de que en algunos casos, al abrir el proyecto con Blend, no era posible editar los controles en la vista de diseño, sino que se habrían por defecto en la vista de código y no permitían cambiar de vista.
 
Me dí cuenta de que los proyectos creados bajo la categoría "WPF Control Library" si permitían abrir los controles en vista de diseño, mientras los creados bajo la categoría "Class Library" eran los que presentaban el problema.
 
Entonces me dí a la tarea de encontrar que era lo que los diferenciaba. Creé un proyecto de cada tipo usando el mismo nombre y luego utilicé el comparador de TFS para comparar los archivos .csproj.
 
Además de algunas referencias a librerías adicionales, el proyecto de libraría de controles contenía las dos líneas siguientes:
 
    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    <WarningLevel>4</WarningLevel>
Procedí a abrir el archivo .csproj del proyecto de librería de clases usando Notepad y le agregué las dos líneas faltantes. Luego lo abrí en Blend y comprobé que efectivamente era posible abrir los controles en la vista de diseño después de efectuar este cambio.

.NET Framework 3.5 será de código abierto.

Como nos informa Scott Gu el día de hoy en su blog, a partir de la versión 3.5 el marco de trabajo .NET de Microsoft tendrá código abierto y será posible para los programadores de cualquiera de los lenguajes del marco de trabajo acceder a la fuente mediante las herramientas de depuración, de manera que sea posible seguir la ejecución del código incluso dentro de las librerías de .NET.
 
Esto es una excelente noticia para todos los programadores que utilizamos alguno de los lenguajes de este marco de trabajo.
 

Excel VBA: Obtener la representación de la columna en cadena de caracteres.

Si se ha trabajado lo suficiente con VBA (específicamente con Excel), y se quiere construir una extensión de aplicación robusta; es muy probable que en algún momento se haya tenido la necesidad de convertir la representación numérica de una columna en su representación como cadena de caracteres (osea, de 1 a A, de 104 a DA, etc.) Esto se puede conseguir fácilmente utilizando la siguiente función:
Public Function GetColumnCharacterRepresentation _
  (ByVal column As Integer) As String
  Dim intFirstCharacter
  intFirstCharacter = Int(column / 26)
  Dim intLastCharacter
  intLastCharacter = IIf(intFirstCharacter = 0, _
    CInt(column Mod 26), CInt(column Mod 26) + 1)
  Dim strFirstCharacter As String
  strFirstCharacter = IIf(intFirstCharacter > 0, _
    Chr(intFirstCharacter + 64), "")
  Dim strLastCharacter As String
  strLastCharacter = Chr(intLastCharacter + 64)
  GetColumnCharacterRepresentation = strFirstCharacter _
   & strLastCharacter
End Function

Expresiones Regulares – 04

Con los metacaracteres que hemos aprendido hasta el momento, es posible efectuar múltiples tipos de búsquedas y validaciones como ya hemos visto en los ejemplos de las entregas anteriores. Sin embargo, los metacaracteres que veremos en esta entrega son los que probablemente aportan más flexibilidad y funcionalidad a las expresiones regulares: Los caracteres de repetición.

Las llaves "{}"

Comúnmente las llaves son caracteres literales cuando se utilizan por separado en una expresión regular. Para que adquieran su función de metacaracteres es necesario que encierren uno o varios números separados por coma y que estén colocados a la derecha de otra expresión regular de la siguiente forma: "\d{2}" Esta expresión le dice al motor de búsqueda que encuentre dos dígitos contiguos. Utilizando esta formula podríamos convertir el ejemplo "^\d\d/\d\d/\d\d\d\d$" que nos servía para validar un formato de fecha en "^\d{2}/\d{2}/\d{4}$" para una mayor claridad en la lectura de la expresión.

Aunque esta forma de encontrar elementos repetidos es muy útil, algunas veces no sabemos cuantas veces se repite lo que búscamos o su grado de repetición es variable. En estos casos los siguientes metacaracteres no son útiles.

El asterisco "*"

El asterisco nos sirve para encontrar algo que se encuentra repetido 0 o más veces. Osea, utilizando la expresión "[a-zA-Z]\d*" nos servirá para encontrar tanto "H" como "H1", "H01", "H100" y "H1000", osea, una letra seguida de un número indefinido de caractéres. Es necesario tener cuidado con el comportamiento del asterisco, ya que este por defecto trata de encontrar la mayor cantidad posible de caracteres que correspondan con el patrón que buscamos. De esta forma si utilizamos "\(.*\)" para encontrar cualquier cosa que se encuentre entre paréntesis y lo aplicamos sobre el texto "Ver (Fig. 1) y (Fig. 2)" esperaríamos que el motor de búsqueda encuentre los textos "(Fig. 1)" y "(Fig. 2)", sin embargo nos sorprenderemos al ver que en su lugar encontrará el texto "(Fig. 1) y (Fig. 2)". Esto sucede porque el asterísco le dice al motor de búsqueda que llene todos los espacios posibles entre dos paréntesis, y ese es el resultado que obtenemos. Si queremos obtener el resultado deseado debemos utilizar el asterisco en conjunto con el signo de pregunta de la siguiente forma: "\(.*?\)" Esto es equivalente a decirle al motor de búsqueda "Encuentre un paréntesis de apertura y luego encuentre cualquier caracter repetido hasta que encuentre un paréntesis de cierre".

El signo de suma "+"

Nos sirve para encontrar algo que se encuentre repetido 1 o más veces. A diferencia del asterisco, la expresión "[a-zA-Z]\d+" encontrará "H1" pero no encontrará "H". También es posible utilizar este metacaracter en conjunto con el signo de pregunta para limitar hasta donde queremos que se efecúe la repetición.

En la entrega anterior hablamos de que los paréntesis redondos establecen un "punto de referencia" para el motor de búsqueda. Estos puntos se denominan grupos y pueden ser anónimos o nominales. A continuación veremos en detalle como utilizar los grupos.

Grupos anónimos

Los grupos anónimos se establecen cada vez que encerramos una expresión regular en paréntesis redondos, por lo que la expresión "<([a-zA-Z]\w*?)>" define un grupo anónimo que tendrá como resultado que el motor de búsqueda almacenará una referencia al texto que coresponda a la expresión encerrada entre los paréntesis.

Pero como podemos utilizar los grupos que establecemos? La forma más inmediata de utilizar los grupos es dentro de la misma expresión regular, lo cual se realiza utilizando la barra inversa "\" seguida del número del grupo al que queremos hacer referencia de la siguiente forma: "<([a-zA-Z]\w*?)>.*?</\1>" Esta expresión regular nos ayudará a encontrar tanto "<font>Esta</font>" como "<B>prueba</B>" en el texto "<font>Esta</font> es una <B>prueba</B>" a pesar de que la expresión no contiene los literales "font" y "B".

Otra forma de utilizar los grupos es en el lenguaje de programación que estemos utilizando. cada lenguaje tiene una forma de distinta de acceder a los grupos, pero como explicamos al principio de la serie explicaremos con detalle la forma utilizada por el .Net Framework, usando la sintáxis de C# (la cual puede facilmente adaptarse a VB.Net o cualquier otro lenguaje del Framework).

Para utilizar el motor de búsqueda del .Net Framework es necesario en primer lugar hacer referencia al espacio de nombres System.Text.RegularExpressions. Luego es necesario declarar una instancia de la clase Regex de la siguiente forma:

Regex _TagParser = new Regex("<([a-zA-Z]\w*?)>");

Luego asumiendo que el texto que queremos examinar con la expresión regular se encuentra en la variable "sText" podemos recorrer todas las instancias encontradas de la siguiente forma:

foreach(Match CurrentMatch in _TagParser.Matches(sText)){
   // —– Código extra aquí —–
}

Luego podemos utilizar la propiedad Groups de la clase Match para traer el resultado de la búsqueda:

foreach(Match CurrentMatch in _TagParser.Matches(sText)){
  String sTagName = CurrentMatch.Groups[1].Value;
}

Grupos nominales

Los grupos nominales son aquellos a los que les asignamos un nombre, dentro de la expresión regular para poder utilizarlos posteriormente. Esto se hace de forma diferente en los distintos motores de búsqueda, así que una vez más aqui explicaremos como hacerlo en el motor del .Net Framework.

Utilizando el ejemplo anterior podemos convertir "<([a-zA-Z]\w*?)>" en "<(?<TagName>[a-zA-Z]\w*?)>". Nótese el signo de pregunta y el texto "TagName" encerrado entre parentesis triangulares, seguido de este. Para utilizar este ejemplo en el .Net Framework utilizaríamos el siguiente código:

Regex _TagParser = new Regex("<(?<TagName>[a-zA-Z]\w*?)>");
foreach(Match CurrentMatch in _TagParser.Matches(sText)){
  String sTagName = CurrentMatch.Groups["TagName"].Value;
}

Es posible definir tantos grupos como sea necesario, de esta forma podemos hacer algo como: "<(?<TagName>[a-zA-Z]\w*?) ?(?<Attributes>.*?)>" para encontrar no solo el nombre del tag HTML sino tambien sus atributos de la siguiente forma:

Regex _TagParser = new Regex("<(?<TagName>[a-zA-Z]\w*?) ?(?<Attributes>.*?)>");
foreach(Match CurrentMatch in _TagParser.Matches(sText)){
  String sTagName = CurrentMatch.Groups["TagName"].Value;
  String sAttributes = CurrentMatch.Groups["Attributes"].Value;
}

Pero podemos ir mucho más allá:
"<?(?<TagName>[a-zA-Z][\w\r\n]*?) ?(?:(?<Attribute>[\w-\r\n]*?)=’?"?(?<Value>[\w-:;,\./= \r\n]*?)’?"? ?)>"
Esta expresión nos permite encontrar el nombre del tag, el nombre del atributo y su valor.

Sin embargo, una tag html puede tener más de un atributo. Este caso lo resolveríamos utilizando repetición de la siguiente forma:
"<?(?<TagName>[a-zA-Z][\w\r\n]*?) ?(?:(?<Attribute>[\w-\r\n]*?)=’?"?(?<Value>[\w-:;,\./= \r\n]*?)’?"? ?)*?>"

Y en el código la utilizariamos de la siguiente forma:

Regex _TagParser = new Regex("<?(?<TagName>[a-zA-Z][\w\r\n]*?) ?(?:(?<Attribute>[\w-\r\n]*?)=’?"?(?<Value>[\w-:;,\./= \r\n]*?)’?"? ?)*?>");
foreach(Match CurrentMatch in _TagParser.Matches(sText)){
  String sTagName = CurrentMatch.Groups["TagName"].Value;
  foreach(Capture CurrentCapture in CurrentMatch.Groups["Attribute"].Captures){
    AttributesCollection.Add(CurrentCapture.Value)
  }
  foreach(Capture CurrentCapture in CurrentMatch.Groups["value"].Captures){
    ValuesCollection.Add(CurrentCapture.Value)
  }
}

Aún más podríamos profundizar utilizando una expresión como esta:
"<?(?<TagName>[a-zA-Z][\w\r\n]*?) ?(?:(?<Attribute>[\w-\r\n]*?)=’?"?(?<Value>[\w-:;,\./= \r\n]*?)’?"? ?)*?>(?<Content>.*?)</\1>"

La cual nos permitiría encontrar el tag, sus atributos, valores y el contenido de esta, y todo con una sola expresión regular!!!!

Espero que les haya gustado esta cuarta entrega. En la próxima continuaremos estudiendo ejemplos y aplicaciones de las expresiones regulares en casos específicos.

No duden en enviarme sus dudas y comentarios al respecto, estaré dispuesto a ampliar la información dada según sea requerido.