Ago 18 2008

Ceibal Jam 2 - Programando para las XO del Plan Ceibal (OLPC) {

Tag: Varios

Laptop XO - Plan Ceibal - OLPC
En Uruguay el plan OLPC se llama Plan Ceibal, y cada tanto se organizan los llamados Ceibal JAM, lo cual es basicamente una reunión de programación donde hay charlas y se organizan actividades para crear programas para las XO.

Este segundo Ceibal Jam se llevará a cabo los días 30/08 y 06/09 en la sede de la Universidad Católica del Uruguay. Siguiendo este enlace podrán ver el cronograma preliminar de actividades.

Via: Varrojo@Linux

}


Ago 18 2008

Aprendamos a escribir funciones recursivas {

Utilizaremos JavaScript para estos ejemplos de recursividad.

Una función es recursiva cuando en su cuerpo hay un llamado a si misma, un ejemplo clásico es la operación matemática potencia, primero veamos la función no recursiva que defina la potencia:

function potencia(base, exponente) {
	 if(exponente == 0) { //caso límite de exponente cero
		return 1
	 } else {
		return base * potencia(base, exponente -1) //llamado recursivo
	 }
}


Para este caso tomaremos sólo las potencias de exponente positivo para no aumentar la complejidad del ejemplo.

Lo que haremos a continuación será analizar la función para convertirla en recursiva, primero los casos límite, sabemos que el resultado de toda potencia de exponente 0 es 1, entonces ese será nuestro primer chequeo.

Luego estudiemos la función a partir de un ejemplo, sea en este caso 24:

  • 24 = 2 * 2 * 2 * 2 = 16
  • 2 * 2 * 2 * 2 = 2 * (23) = 2 * 8 = 16
  • 2 * (23) = 2 * (2 * (22)) = 2 * (2 * 4) = 16

Visto lo anterior, podemos afirmar que xy = x * (xy-1) de donde claramente se desprende la recursividad, en palabras, potencia de x a la y = x por potencia de x a la y -1, vamos el código:

function potencia(base, exponente) { if(exponente == 0) { //caso límite de exponente cero return 1; } else { while(exponente >= 1) { return base * potencia(base, exponente -1); //llamado recursivo } } } 

Tal vez en este caso no es muy notorio, pero una de las principales ventajas de utilizar algoritmos recursivos es la disminución de la cantidad de líneas de código necesarias.

Estudiemos el caso de la sucesión de Fibonacci, otro ejemplo clásico de algoritmo recursivo.

Cada término de la sucesión de Fibonacci es la suma de los 2 términos predecesores, sabiendo que los primero términos, por definición son 0 y 1, entonces sabemos que los primeros 10 términos de la sucesión son:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34

Ahora podemos afirmar que además de los términos primarios f0 = 0, f1 = 1, un término enésimo se define como fn = fn-1 + fn-2

Veamos una función recursiva que calcule el término n de la sucesión de Fibonacci:

function fibonacci(n) {
	if(n==0  n== 1) { // casos límite 
		return n 
	} else { 
		return fibonacci(n-1) + fibonacci(n-2) // suma del término anterior y su predecesor 
	} 	
}

Si llamamos a la función anterior en un bucle podremos obtener la sucesión hasta el término especificado en el bucle, por ejemplo:

var fib = "F: " 
for(i = 0 i&lt= 9 i++) { 
	fib += fibonacci(i) + "  " 
} 
document.write(fib)

Nos escribirá los primeros 10 términos de la sucesión de Fibonacci: F: 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 |

}


Ago 14 2008

Nace PyUy - Grupo de Usuarios Python del Uruguay {

Tag: Varios

Python logo
Marcelo Ramos escribe en su blog:

Acabo de crear el grupo PyUy en Google Groups para que podamos comenzar a darle forma al grupo y por supuesto hablar de todo lo relativo a Python.

Así que invito a todos los interesados a anotarse en la siguiente dirección:

http://groups.google.com/group/pyuy

Nos vemos en PyUy!

Ya estoy adentro para apoyar la iniciativa, además de que Python es uno de los lenguajes que quiero aprender desde hace bastante tiempo. Vamos a ver que resulta… se verá en los posts de programación en Python que aparezcan en el blog.

Además Fernando ya registró el canal IRC #pyuy en irc.freenode.net

}


Ago 14 2008

Como filtrar una lista de objetos con LINQ y ver las propiedades por Reflection (VB.Net) {

Tag: LINQ, VB.Net

LINQ es un proyecto de Microsoft que agrega a los lenguajes del .Net Framework la capacidad de utilizar consultas de sintáxis parecida a SQL. Inicialmente sólo se itegró a C# y VB.Net.

En el sitio de Microsoft hay una traducción de la página del proyecto LINQ donde se puede leer más al respecto.

En nuestro ejemplo utilizaremos LINQ To Objects, que es el término que se utiliza para definir la utilización de LINQ con cualquier colección que implemente las interfaces IEnumerable o IEnumerable(T).

En nuestro caso hemos definido una clase Objeto que tiene las propiedades ID : Integer, Tipo : String, Tamaño : Decimal y Habilitado : Boolean. Para utilizar LINQ hemos creado una colección del tipo List(Of Objeto) la cual cargamos con varias instancias de nuestra clase Objeto.

La idea es crear un filtro dinámico, para dar la posibilidad al usuario de seleccionar el valor para 2 propiedades y crear un filtro con OR o AND, o sea Propiedad1 = a OR/AND Propiedad2 = b.

Nuestra intención es poder reutilizar el código, entonces no podemos crear 2 ComboBox y cargar las propiedades a mano, por lo que recurriremos al namespace System.Reflection para extraer las propiedades de nuestra clase Objeto.

Según Microsoft: El espacio de nombres System.Reflection contiene clases e interfaces que proporcionan una vista administrada de los campos, los métodos y los tipos cargados, con la posibilidad de crear e invocar tipos dinámicamente.

Private Sub CargarPropiedades()
	Dim propiedades1 As New List(Of String)
	Dim propiedades2 As New List(Of String)
 
	' Recorremos todos los miembros de la clase
	For Each propiedad As System.Reflection.MemberInfo In System.Reflection.Assembly.GetExecutingAssembly.GetType("Objeto").GetMembers()
		' Filtramos para seleccionar solamente las propiedades
		If propiedad.MemberType = System.Reflection.MemberTypes.Property Then
			propiedades1.Add(propiedad.Name)
			propiedades2.Add(propiedad.Name)
		End If
	Next
 
	Me.cmbField1.DataSource = propiedades1 'Asignamos el DataSource a nuestros ComboBox
	Me.cmbField2.DataSource = propiedades2
End Sub

Con ese código tan simple ya tenemos 2 combos cargados con las propiedades de nuestra clase Objeto. En este caso ob tuvimos el tipo Objeto del mismo ensamblado, (Assembly), en el que estamos trabajando, pero pudimos haberlo buscado en otro Assembly.
Cabe aclarar que se utilizan 2 listas, una para cada combo porque si seteamos la misma lista como DataSource para los 2 ComboBox, al cambiar el valor seleccionado en uno, se cambia también en el otro.

Sólo resta armar nuestra sentencia LINQ para filtrar la coleeción de Objeto. Para ello tenemos que tomar: 1) la primera propiedad seleccionada por el usuario, 2) el valor que ingresó para esa propiedad, 3) la condición que seleccionó (AND/OR), 4) la segunda propiedad seleccionada, 5) el valor ingresado para la segunda propiedad.

Lo que haremos será armar la sentencia de la siguiente manera:

  • Seleccionar todos los objetos con PropiedadSeleccionada1 = ValorIngresado1
  • AND Si el usuario seleccionó ‘AND’ PropiedadSeleccionada2 = ValorIngresado2, sino True
  • OR Si el usuario seleccionó ‘OR’ PropiedadSeleccionada2 = ValorIngresado2 sino False.

Entonces la sentencia, en pseudo-código se vería de una se las siguientes maneras:

  • Seleccionar todos los objetos con Propiedad1 = Valor1 AND Propiedad2 = Valor2 OR False
  • Seleccionar todos los objetos con Propiedad1 = Valor2 AND True OR Propiedad2 = Valor2

De esa manera con una misma sentencia se cubren los 2 casos, veamos el código:

Private Sub btnSelect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSelect.Click
	If ValidarEntrada() Then ' Chequeaar que el usuario haya ingresado todos los valores necesarios
		Try
			' LINQ To Objects
			Dim resSelect = From obj In mObjetos _
				Select obj _
				Where obj.GetType().GetProperty(Me.cmbField1.SelectedItem.ToString()).GetValue(obj, Nothing) = Me.txtCond1.Text _
				And (IIf(cmbJoin.SelectedItem = "AND", obj.GetType().GetProperty(Me.cmbField2.SelectedItem.ToString()).GetValue(obj, Nothing) = Me.txtCond2.Text, True)) _
				Or (IIf(cmbJoin.SelectedItem = "OR", obj.GetType().GetProperty(Me.cmbField2.SelectedItem.ToString()).GetValue(obj, Nothing) = Me.txtCond2.Text, False))
 
			Me.lstSelect.Items.Clear() ' Limpiar la lista antes de mostrar el resultado de la consulta
			For Each item In resSelect
				Me.lstSelect.Items.Add(item)
			Next
		Catch ex As Exception
			If MessageBox.Show(String.Format("Error: {0}{1}Desea ver más información acerca de este error?", ex.Message.ToString(), Environment.NewLine), "Error", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) = Windows.Forms.DialogResult.Yes Then
				MessageBox.Show(ex.ToString(), "Detalle del error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
			End If
		End Try
	End If
End Sub

Descargar el código fuente de este ejemplo.

}


Ago 11 2008

Aplicación para calcular la cantidad de billetes a partir del importe en VB.Net {

Tag: VB.Net

Esta es una aplicación muy simple, la misma calcula la cantidad de billetes/monedas de cada denominación necesarios para cubrir un importe tomando en cuenta que siempre vamos a querer completar el importe con los billetes/monedas de mayor denominación posible.

O sea que para cubrir el importe $ 150 vamos a usar un billete de $ 100 y otro de $ 50, pero no uno de $ 100 y 2 de $ 20.

Cabe destacar que como este es sólo un ejemplo, las denominaciones no son configurables, están incluidas en el código fuente y las mismas son correspondientes a la moneda de Uruguay, el Peso Uruguayo.

Para guardar las denominaciones y luego la cantidad necesaria de cada una utilizamos un objeto de tipo Generic.Dictionary(Of Decimal, Integer) en el cual guardaremos como key cada denominación:

Private Sub CargarBilletes(ByRef lista As Generic.Dictionary(Of Decimal, Integer))
    lista = New Generic.Dictionary(Of Decimal, Integer)
    With lista
        .Add(2000, 0) ' Billetes
        .Add(1000, 0)
        .Add(500, 0)
        .Add(200, 0)
        .Add(100, 0)
        .Add(50, 0)
        .Add(20, 0)
        .Add(10, 0) ' Monedas
        .Add(5, 0)
        .Add(2, 0)
        .Add(1, 0)
        .Add(0.5, 0)
    End With
End Sub

La función anterior es llamada cada vez que se hace el cálculo, de esa manera nos aseguramos que nuestros valores han sido reseteados, aunque en una aplicación más compleja éstos valores deberían obtenerse desde una base de datos o un archivo de configuración.

Public Sub DiscriminarBilletes(ByVal Importe As Decimal)
    Dim keys As Decimal() = New Decimal(Billetes.Count - 1) {} ' Creamos un array de Decimal para guardar las denominaciones
    Billetes.Keys.CopyTo(keys, 0) ' Copiamos las keys del objeto Generic.Dictionary(Of Decimal, Integer)
    For Each billete As Decimal In keys
        While Importe >= 0 AndAlso Importe >= billete ' Si el importe > 0 y es > la denominación actual sumamos 1
            Billetes(billete) += 1
            Importe -= billete ' Descontamos del importe el valor de la denominación actual
        End While
    Next
 
    Mostrar() ' Mostramos los resultados
End Sub

La función anterior es la que realiza todo el cálculo, se puede ver que es muy simple. Alguien debe estar preguntándose por qué copiar las keys a otro array en lugar de recorrer el objeto Dictionary directamente, la respuesta es que Visual considera que se modificó el enumerado cada vez que se suma 1, entonces no se puede seguir recorriendo el Dictionary.

Por las dudas aclaro el uso de AndAlso: funciona como And, pero en caso de no cumplirse la primera condición no se chequea la segunda. Es una mejora que se introdujo en VB.Net ya que en VB6 se tenían los operadores And y Or. También se agregó el operador lógico OrElse.

Descargar el código fuente de este ejemplo.

}


Ago 09 2008

Método de ordenación de la burbuja (bubble sort) en Python {

Tag: Algoritmos, Python

El método de la burbuja o método de intercambio directo es el algoritmo de ordenación más simple. El mismo compara los elementos a ordenar de a pares, cada uno con su siguiente y si están en el orden equivocado los intercambia y el proceso debe realizarse varias veces hasta que la lista esté totalmente ordenada, pero al ser un algoritmo tan simple, a pesar de ser efectivo, el mismo no es muy eficiente, su orden es n2

Por ejemplo en la lista [3,1,2,0] se harán los siguientes movimientos: (en negrita los elementos comparados)

# de comparación Estado inicial Estado final
1 3,1,2,0 1,3,2,0
2 1,3,2,0 1,2,3,0
3 1,2,3,0 1,2,0,3
4 1,2,0,3 1,2,0,3
5 1,2,0,3 1,0,2,3
6 1,0,2,3 1,0,2,3
7 1,0,2,3 0,1,2,3

Ahora vamos a ver la función en Python para implementar el método de la burbuja:

def ordenar(items):
    i = 0 # Inicializar las variables
    j = 0
    for i in range(len(items)): # recorrer toda la lista
        for j in range(len(items) -1): # recorrer toda la lista haciendo las comparaciones
            if items[j] > items[j+1]: # comparar
                aux = items[j]
                items[j] = items[j+1]
                items[j+1] = aux

}


Ago 08 2008

Category2Post en el directorio de plugins de Wordpress.org {

Tag: Category2Post

Así es, la semana pasada hice una solicitud para incluir Category2Post en el repositorio oficial de plugins de Wordpress y la solicitud fue aceptada, así que desde ahora el plugin figura en el directorio y tiene su repositorio SVN correspondiente.

Página en el directorio de plugins: http://wordpress.org/extend/plugins/category2post/

Repositorio SVN: http://svn.wp-plugins.org/category2post/

}


Ago 07 2008

Validar formularios web con JavaScript y Expresiones Regulares {

Tag: JavaScript

En este post vamos a validar un formulario web con 3 campos, un campo Nombre que será obligatorio, un campo Email que será obligatorio y un campo numérico que será opcional pero sólo podrá contener números.

Para validar los campos email y numérico utilizaremos expresiones regulares, ya que es la manera más fácil, y a mi entender correcta, de validar el contenido de un campo.

En el formulario web utilizamos el evento onsubmit junto con una función de JavaScript que retorne true cuando la validación de los campos sea correcta, para que el formulario no complete el submit en caso de un error en la validación al onsubmit no le escribiremos sólo el nombre de la función, sino que utilizaremos return junto con el nombre de la misma.

function validar(form) {
	var emailRegEx = /^((\w\.){2,}@)\w{3,}\.\w{2,4}((\.(\w{2}))?)?$/
	var numericoRegEx = /^\d*$/
 
	if(form.txtNombre.value == "") {
		form.txtNombre.focus()
		alert("El campo 'Nombre' es obligatorio!")
		return false
	}
	if(form.txtEmail.value == "") {
		form.txtEmail.focus()
		alert("El campo 'Email' es obligatorio!")
		return false
	} else {
		if(!form.txtEmail.value.match(emailRegEx)) {
			form.txtEmail.focus()
			form.txtEmail.value = ""
			alert("Debe ingresar una dirección de email válida.")
			return false
		}
	}
	if(form.txtNumero.value !== "") {
		if(!form.txtNumero.value.match(numericoRegEx)) {
			alert("El campo 'Campo numérico' sólo puede contener números.")
			form.txtNumero.focus()
			form.txtNumero.value = ""
			return false
		}
	}
	return true
}

La función que tenemos arriba de estas líneas hace una validación y muestra el mensaje de error al estilo antiguo: con un messagebox, en javascript alert(); pero en estos días que están de moda los formularios que usan tecnología ajax, adaptaremos la función para que en lugar de mostrar el error en el messagebox, lo muestre en una celda de la tabla que contiene los campos del formulario, para ello recurriremos a la función de javascript document.getElementById(ElementId);

function validar2(form) {
	var emailRegEx = /^((\w\.){2,}@)\w{3,}\.\w{2,4}((\.(\w{2}))?)?$/
	var numericoRegEx = /^\d*$/
 
	if(form.txtNombre.value == "") {
		form.txtNombre.focus()
		mostrar("El campo 'Nombre' es obligatorio!")
		return false
	}
	if(form.txtEmail.value == "") {
		form.txtEmail.focus()
		mostrar("El campo 'Email' es obligatorio!")
		return false
	} else {
		if(!form.txtEmail.value.match(emailRegEx)) {
			form.txtEmail.focus()
			form.txtEmail.value = ""
			mostrar("Debe ingresar una dirección de email válida.")
			return false
		}
	}
	if(form.txtNumero.value !== "") {
		if(!form.txtNumero.value.match(numericoRegEx)) {
			mostrar("El campo 'Campo numérico' sólo puede contener números.")
			form.txtNumero.focus()
			form.txtNumero.value = ""
			return false
		}
	}
	return true
}
 
function mostrar(error) {
	document.getElementById('Errores').innerHTML = error
	document.getElementById('Errores').style.background = "#ffcccc"
}

Haz click aquí para ver este ejemplo funcionando.

}


Ago 06 2008

Capturar una imagen de la ventana activa con VB.Net {

Tag: Mini Tips, VB.Net

Muchas veces nos es útil capturar una imagen del momento en que se produce un error para saber qué sucedió o cómo solucionarlo. Sin ir más lejos, en mi trabajo anterior instalamos una aplicación y a veces teníamos un error que después de hacer guardias de 8hs frente a los usuarios no pudimos encontrar y las explicaciones y suposiciones de los usuarios carecían totalmente de sentido.

Por eso mismo muchas veces es bueno capturar el estado de la aplicación en el momento, en este ejemplo vamos a capturar una imágen de la ventana activa y la vamos a guardar.

Lo primero que haremos será la función que captura la imágen, para eso utilizaremos el viejo y conocido recurso de apretar la tecla PRINT SCREEN, y para eso utilizaremos la función SendKeys.Send.

    Private Sub ImprimirPantalla()
        SendKeys.Send("{PRTSC}")
        GuardarImagenDesdeClipboard()
    End Sub

Lo que hemos hecho hasta este momento es capturar la imagen, la misma queda en el portapapeles de Windows, así que para que nos sea útil necesitamos guardarla en un archivo debidamente identificado, para ello extraeremos la imagen del portapapeles y nos crearemos un archivo cuyo nombre se comprondrá de la fecha-hora actual y el nombre de la clase que generó la excepción.

    Private Sub GuardarImagenDesdeClipboard()
        If Clipboard.ContainsImage() Then
            Dim NombreArchivo As String = String.Format("{0}_{1}.jpg", DateTime.Now.ToString("yyyyMMdd-HHmmss"), Me.Name)
            Dim Path As String = String.Format("{0}\logs\imagenes\{1}", Application.StartupPath, NombreArchivo)
            Dim img As Image = Clipboard.GetImage()
            img.Save(Path)
        End If
    End Sub

Hay que tener en cuenta que para que la imágen se guarde es necesario que el directorio donde se va a guardar exista previamente, por eso sería conveniente chequear su existencia y si es necesario crearlo, antes de intentar guardar la imagen.

}


Jul 30 2008

Ordenar una lista con expresiones Lambda (múltiples criterios) VB.Net {

Tag: VB.Net

Este post se trata de como ordenar una lista de objetos de acuerdo a varios criterios utilizando una sola expresión lambda. El ejemplo está hecho utilizando el .net framework 3.5 (Visual Studio 2008).

Tenemos una lista de objetos con la siguiente estructura:

Public Class Elemento
    Public Sub New(ByVal mNum As Integer, ByVal mPrioridad As Prioridades, ByVal mValor As Integer)
        Numero = mNum
        Prioridad = mPrioridad
        Valor = mValor
    End Sub
 
    Public Enum Prioridades
        Alta = 0
        Media = 1
        Baja = 2
    End Enum
 
    Public Numero As Integer
    Public Prioridad As Priorities
    Public Valor As Integer
End Class

Para este ejemplo utilizaremos un objeto List(Of Elemento) que llenaremos con valores aleatorios y necesitaremos ordenarla de acuerdo a los siguientes criterios:

  • Primero: Numero en orden ascendente
  • Segundo: Prioridad de mayor a menor
  • Tercero: Valor en orden ascendente

Supongamos que nuestra lista se completó con los siguientes elementos:

Num Prioridad Valor
4 Baja 16
1 Alta 26
3 Media 87
4 Media 10
2 Baja 3
5 Alta 4
4 Media 134
2 Baja 342

Nuestro resultado debe ser el siguiente:

Num Prioridad Valor
1 Alta 26
2 Baja 3
2 Baja 342
3 Media 87
4 Media 10
4 Media 134
4 Baja 16
5 Alta 4

Por lo tanto nuestra expresión lambda será la siguiente:

Public Sub LambdaSort(ByVal lista As List(Of Element))
        lista.Sort(Function(x, y) _
                x.Numero.CompareTo(y.Numero) Or _
                (x.Numero.Equals(y.Numero) And x.Prioridad.CompareTo(y.Prioridad)) Or _
                (x.Numero.Equals(y.Numero) And x.Prioridad.Equals(y.Prioridad) And x.Valor.CompareTo(y.Valor)))
End Sub

La expresión está hecha en una sola línea que fue separada para comodidad en la lectura, por lo que iremos viendo linea a linea, en la primera declaramos la expresión lambda que va a ordenar la lista:

lista.sort(Function(x,y)

luego vamos ennumerando nuestras condiciones:

x.Numero.CompareTo(y.Numero) Comparamos el valor de x.Numero con el de y.Numero, esta comparación nos devuelve el orden ascendente o sea x < y.
(x.Numero.Equals(y.Numero) And x.Prioridad.CompareTo(y.Prioridad)) Si x.Numero = y.Numero comparamos la Prioridad de ambos al igual que lo hicimos en el punto anterior con Numero.
(x.Numero.Equals(y.Numero) And x.Prioridad.Equals(y.Prioridad) And x.Valor.CompareTo(y.Valor)) Si x.Numero = y.Numero y también x.Priridad = y.Pririodad comparamos el Valor.

Separamos cada uno de los criterios de ordenación con OR para que se aplique uno u otro y listo.

Sin duda una forma simple y rápida de ordenar una lista.

}


Página 1 de 212»