Algoritmo para desordenar un arreglo en C/C++

jueves, julio 31, 2008

Imagina que deseas implementar un algoritmo en C++ donde necesites desordenar aleatoriamente un arreglo; por ejemplo: en un juego donde utilices un mazo de cartas y debas barajarlo. El siguiente código puede ayudarte en esa tarea:

int mazo_ordenado[44];
int mazo_barajado[44];
bool usado[44];

for (int i=0; i < 44; i++)
usado[i]=false;

int index=0;
for (int i=0; i < 44; i++){
do{
index = (rand() % 44);
while (usado[index]);
mazo[i] = mazo_ordenado[index];
usado[index]=true;
}

Ahora, explicaré el código paso a paso. La intención es desordenar un arreglo de 44 elementos (puede ser de cualquier tamaño, solo basta reemplazar el 44 por el número de su elección). El arreglo ordenado lo tenemos en la variable mazo_ordenado. Luego creamos otros dos arreglo con la misma cantidad de elementos, uno llamado mazo_barajado donde almacenaremos el arreglo desordenado y otro llamado usado en donde guardaremos el estado de cada elemento del mazo original.

int mazo_ordenado[44];
int mazo_barajado[44];
bool usado[44];

La idea es recorrer en orden creciente el arreglo desordenado y depositar en cada uno de sus elementos un elemento aleatorio del arreglo ordenado. Con el arreglo de booleanos usado llevaremos la cuenta de cuáles elementos del arreglo original se han usado y cuáles no (con la finalidad de no duplicar elementos), por eso debemos inicializar todos sus elementos en false

for (int i=0; i < 44; i++)
usado[i]=false;

Usando la función rand() generamos índices aleatorios para obtener los elementos del arreglo original; pero debemos comprobar el valor de usado[indice] para saber si el elemento ha sido usado o no. Si el elemento ya está usado, el valor de usado[indice] será true y tendremos que generar otro índice hasta que consigamos uno no usado.

do{
index = (rand() % 44);
while (usado[index]);

Si no hemos usado el elemento apuntado por indice, el valor de usado[indice] será false y entonces procedemos a almacenar el elemento en el arreglo desordenado y cambiamos el valor de usado[indice] a true.

mazo[i] = mazo_ordenado[index];
usado[index]=true;

Esto debemos hacerlo para los 44 elementos del arreglo desordenado así que debe ir dentro de un for y con la respectiva inicialización de la variables:

int index=0;
for (int i=0; i < 44; i++){
do{
index = (rand() % 44);
while (usado[index]);
mazo[i] = mazo_ordenado[index];
usado[index]=true;
}

A la salida del for tendremos un arreglo desordenado listo para usar :D.

Prueben el código, agreguen unos cuantos printf para imprimir los valores de los mazos antes y después del for y comenten sus resultados. Si tienen alguna sugerencia o corrección posteenla también que será bien recibida. Espero que les haya sido de utilidad.

Instalar plugin Atlantis para Compiz en Hardy Heron

miércoles, julio 30, 2008


Este nuevo plugin de compiz permite poner tu escritorio como una pecera y es muy fácil de instalar.

  1. Descarga el plugin desde aquí

  2. Instala las depencias:
    $ sudo apt-get install compiz-dev compiz-bcop libtool

  3. Compila e instala el plugin
    $ make clean
    $ make
    $ make install

Ahora puedes ir al menú Sistema->Preferencias->Configuración avanzada de los efectos de escritorio para activar y configurar tu nuevo y flamante plugin Cube Atlantis

SciTE: Mi editor de texto favorito

domingo, julio 27, 2008




SciTE es un excelente editor de texto que fue desarrollado en un principio para demostrar el poder de Scintilla (un componente/librería para la edición de texto). Sin embargo ha crecido tanto que ha llegado a opacar un poco a la propia librería.

¿Y qué tiene de grandioso el SciTE? se preguntarán. Pues quizás no sea nada del otro mundo, pero es que su sencillez, su funcionalidad y su alto grado de personalización lo hacen (al menos para mi) el editor de texto perfecto. Al momento de escribir este post SciTE está disponible en las arquitecturas de 32 bits para sistemas GNU/Linux y Windows.

En la lista que sigue trataré de describir las funcionalidades básicas del SciTE:
  • Edición de Texto: Estándar y con resaltado de sintaxis. Soporta gran cantidad de lenguajes de programación y puede expandirse para lenguajes que aún no estén soportados

  • Subsistema de comandos: Permite ejecutar herramientas (compiladores, interpretes, etc) dentro de la misma interfaz del SciTE

  • Pestañas: Permite abrir entre 1-100 documentos al mismo tiempo, visualizando uno a la vez y los demás en memoria. Además se puede guardar el estado de las pestañas en archivos de sesiones y recuperarlas cuando se desee

  • Atajos de teclado: Facilitan la interacción entre el usuario y el editor (siguen las convenciones más comunes de GNU/Linux y Windows)

  • Abreviaturas: Una función poderosa constituida por pares abrev = texto definidos por el usuario. Al escribir abrev en el editor y presionar Ctrl+B, se reemplaza abrev por texto

  • Plegado: Una de mis funciones favoritas. Permite plegar o expandir fragmentos de código basados en identación (en el caso de Python) o en llaves de apertura y cierre (en el caso de otros lenguajes). Muestra símbolos al margen izquierdo del editor para expandir o contraer los fragmentos

  • Archivos de propiedades: Permiten definir el comportamiento y la configuración general del editor

Luego de mencionar algunas de las características del SciTE veamos como personalizarlo. SciTE posee 4 tipos de archivos de configuración:
  • "SciTE.properties" (propiedades locales)

  • "SciTEDirectory.properties" (propiedades de directorio)

  • ".SciTEUser.properties" en GNU/Linux o "SciTEUser.properties" en Windows (propiedades de usuario)

  • "SciTEGlobal.properties" (propiedades globales)

El archivo de propiedades locales debe estar presente en el mismo directorio donde se encuentra el archivo que estamos editando.

El archivo de propiedades de directorio se usa para definir el comportamiento del editor (o de sus herramientas) sobre todos los archivos contenidos dentro de un directorio.

El archivo de propiedades de usuario define el comportamiento del editor para cada usuario del equipo y se encuentra en el directorio home del usuario en los sistemas GNU/Linux o en el directorio de perfil de usuario definido en la variable USERPROFILE de Windows (si la variable USERPROFILE no está definida se ubica en el directorio del ejecutable)

El archivo de propiedades globales define el comportamiento por defecto del editor y se encuentra en /usr/share/scite para los sistemas GNU/Linux y en el directorio del ejecutable para Windows.

Las propiedades locales anulan a las propiedades de usuario que a su vez anulan a las propiedades globales.

Ahora voy a comentar la configuración que he realizado del SciTE usando el archivo de propiedades de usuario (".SciTEUser.properties" en mi caso):

# Se define el ancho de una tabulación equivalente a 4 espacios en blanco, se
# establece el ancho de la identación a 4 caracteres y se indica que se usarán
# espacios en lugar de tabulaciones para la identación
tabsize=4
indent.size=4
use.tabs=0

# Define la cantidad de pestañas simultáneas
buffers=15

# Permite visualizar una línea en el borde derecho del editor con un ancho de
# 100 caracteres y de color #C0DCC0
edge.column=100
edge.mode=1
edge.colour=#C0DCC0

# Muestra una lista de autocompletado cuando se escriben palabras que ya se
# encuentran dentro del texto
autocompleteword.automatic=1

# Visualiza el número de línea en el márgen izquierdo
line.margin.visible=1

Para una descripción detallada de cada una de las propiedades del SciTE visite la página de documentación oficial


Actualización: 13/11/2008

Acá les dejo mi archivo personal de configuración del SciTE; allí, además de lo mencionado arriba, configuro el editor para que use fuentes monospace y uno que otro truquillo :D

# Se define el ancho de una tabulación equivalente a 4 espacios en blanco, se
# establece el ancho de la identación a 4 caracteres y se indica que se usarán
# espacios en lugar de tabulaciones para la identación
tabsize=4
indent.size=4
use.tabs=0

# Define la cantidad de pestañas simultáneas
buffers=15

# Permite visualizar una línea en el borde derecho del editor con un ancho de
# 100 caracteres y de color #C0DCC0
edge.column=80
edge.mode=1
edge.colour=#C0DCC0

# Muestra una lista de autocompletado cuando se escriben palabras que ya se
# encuentran dentro del texto
autocompleteword.automatic=1

# Visualiza el número de línea en el márgen izquierdo
line.margin.visible=1

# Default
style.*.32=$(font.monospace)
style.cpp.32=$(font.monospace)
style.python.32=$(font.monospace)
# Line number
#style.*.33=back:#C0C0C0,$(fontmonospace)
# Brace highlight
#style.*.34=fore:#0000FF,bold
# Brace incomplete highlight
#style.*.35=fore:#FF0000,bold
# Control characters
#style.*.36=
# Indentation guides
#style.*.37=fore:#C0C0C0,back:#FFFFFF

font.base=font:!Bitstream Vera Sans Mono,size:9
font.small=font:!Bitstream Vera Sans Mono,size:8
font.comment=font:!Bitstream Vera Sans Mono,size:9
font.code.comment.box=$(font.comment)
font.code.comment.line=$(font.comment)
font.code.comment.doc=$(font.comment)
font.code.comment.nested=$(font.comment)
font.text=font:!Bitstream Charter Mono,size:9
font.text.comment=font:!Bitstream Vera Sans Mono,size:9
font.embedded.base=font:!Bitstream Vera Sans Mono,size:9
font.embedded.comment=font:!Bitstream Vera Sans Mono,size:9
font.monospace=font:!Bitstream Vera Sans Mono,size:9
font.vbs=font:!Bitstream Vera Sans Mono,size:9


Los invito a que lo prueben y digan que les parece... para mi es el mejor y ¿para ti?

Problemas instalando GRUB en Debian Lenny

miércoles, julio 23, 2008

Estuve instalando Debian Lenny en un pentium II ~ 300MHz con 128MB de memoria RAM y par de discos de 4.3GB cada uno y resulta que cada vez que llegaba al paso de Configurar gestor de arranque GRUB me saltaba el error Grub package failed to install into /target/ y no podía terminar la instalación.

Al principio pensaba que se trataba de algún daño en los discos, intenté instalar Debian con distintas opciones de HW, probando cada disco por separado, usando diferentes sistemas de archivos y nada.

Me puse a buscar en google y me topé con esta excelente guía de instalación de Red Hat y allí encontré la respuesta. Resulta que los BIOS de las máquinas viejas no pueden acceder más allá del cilindro 1024 de los discos duros y esto equivale aproximadamente a 528MB (la cifra exacta depende del BIOS y del disco duro).

¿Pero que significa esto? Pues muy sencillo, que al momento de crear la tabla de particiones del disco debemos reservar un espacio en los primeros 1024 cilindros del disco duro (<= 528MB) para la partición /boot y así permitir que la data del GRUB e incluso el kernel Linux se ubiquen en esa zona. Con esto nos aseguramos de que el BIOS puede acceder a la data y bootear correctamente.

Configurar sonido 5.1 en Ubuntu Hardy Heron

martes, julio 22, 2008

Desde hace algún tiempo tenía este tópico pendiente y hoy me decidí a resolverlo y publicar mis resultados. Trataré de explicar paso a paso lo que hice para lograr el tan anhelado sonido 5.1 en Ubuntu Hardy Heron.

Ubuntu Hardy Heron ya incluye PulseAudio así que no hace falta instalarlo (para ver una lista de todas las distribuciones haga clic aquí), sin embargo a simple vista no es posible notar su presencia porque no se incluyen las herramientas auxiliares. Lo que haremos será usar PulseAudio como reemplazo del ESD y configurar ALSA para que use PulseAudio.

La configuración de ALSA se guarda en un par de archivos ocultos en nuestro directorio home, ellos son .asoundrc y .asoundrc.asoundconf. Si estos archivos existen debemos borrarlos/renombrarlos a fin de evitar cualquier error por una configuración residual. Para lograr esto escribimos en el terminal:

$ cd ~
$ mv .asoundrc .asoundrc_old
$ mv .asoundrc.asoundconf .asoundrc.asoundconf_old


Las instrucciones anteriores nos posicionan en nuestro home y renombran los archivos .asoundrc y .asoundrc.asoundconf a .asoundrc_old y .asoundrc.asoundconf_old respectivamente. La instrucción cd ~ puede reemplazarse por cd /home/mi_directorio.

Ahora hacemos que ALSA genere estos archivos automáticamente. Primero listamos el nombre de nuestra tarjeta de sonido:

$ asoundconf list

Y el nombre que nos muestre el comando anterior lo usaremos en:

$ asoundconf set-default-card nombre_de_la_tarjeta

Posteriormente procedemos a editar el archivo de configuración del PulseAudio:

$ sudo gedit /etc/pulse/daemon.conf

Allí ubicaremos la siguiente línea:

;default-sample-channels = 2

y la reemplazaremos por:

default-sample-channels = 6

Lo que hacemos es quitar el ; para que la línea sea tomada en cuenta y cambiamos la cantidad de canales de 2 a 6.

Ahora hay que asegurarse que PulseAudio no intentará abrir el dispositivo por "defecto" para su propia salida de audio. Para ello abrimos el archivo:

$ sudo gedit /etc/pulse/default.pa

Y buscamos el siguiente fragmento de texto:

### Automatically load driver modules depending on the hardware available
.ifexists module-hal-detect.so
load-module module-hal-detect
.else
### Alternatively use the static hardware detection module (for systems that
### lack HAL support)
load-module module-detect
.endif


Debemos comentar todas estas líneas, para dejarlo así:

### Automatically load driver modules depending on the hardware available
#.ifexists module-hal-detect.so
#load-module module-hal-detect
#.else
### Alternatively use the static hardware detection module (for systems that
### lack HAL support)
#load-module module-detect
#.endif


E inmediatamente después de ese fragmento de texto agregamos la línea:

load-module module-alsa-sink device=hw:0

Una cosa importante que se debe aclarar es que PulseAudio crea sus propios grupos y todos los usuarios que quieran usar este servidor de sonidos deben pertenecer a ellos. Para que el usuario pertenezca a estos grupos ejecutamos las siguientes instrucciones:

$ sudo adduser nombre_usuario pulse
$ sudo adduser nombre_usuario pulse-access
$ sudo adduser nombre_usuario pulse-rt


Luego vamos hasta el menú Sistema->Preferencias->Sonido, en la pestaña Dispositivos seleccionamos PulseAudio Sound Server para todas las opciones y como dispositivo mezclador seleccionamos el nombre de nuestra tarjeta de sonido.



En la pestaña Sonidos nos aseguramos que la opción Activar mezcla de sonidos por software (ESD) esté activada.



Sólo nos resta reiniciar el ALSA y el PulseAudio, para esto escribimos en el terminal:

$ sudo /etc/init.d/pulseaudio restart
$ sudo /sbin/alsa reload


Con esto ya deberíamos tener todos nuestros altavoces funcionando. Recuerda verificar que el volumen está en el nivel adecuado (que no está muy bajo o silenciado), para ello cuentas con:

$ alsamixer

¿Te ha funcionado ésta configuración? Deja tu comentario y cuenta cuáles han sido tus resultados

Eventos de ratón en el QGraphicsView

miércoles, julio 16, 2008

El QGraphicsView es una clase de Qt4 que proporciona un widget para mostrar una escena QGraphicsScene. La escena es una superficie que nos permite manejar un montón de elementos 2D, sin embargo ninguno de estos controles trae habilitado por defecto la captura de eventos de ratón.

Para interceptar (y manejar) estos eventos debemos hacer una subclase, bien sea, de QGraphicsScene o de QGraphicsView y redefinir el método mousePressEvent. Pero como QGraphicsView contiene a la escena (digamos que es el widget padre) entonces lo tomaremos como base para esta explicación.

Vamos a definir una subclase válida de un QGraphicsView llamada GraphicsView y que tenga una señal llamada mousePressed con dos argumentos enteros:
#include <QGraphicsView>
#include <QObject>

class GraphicsView : public QGraphicsView{
Q_OBJECT
public:
GraphicsView(QWidget *parent = 0);
void mousePressEvent(QMouseEvent *event);
signals:
void mousePressed(int x, int y);
};

El método mousePressEvent se llamará cada vez que el usuario haga clic en un botón del ratón encima del GraphicsView. Para implementar otros eventos de ratón podemos redefinir (de la misma manera) las funciones mouseMoveEvent, mouseReleaseEvent, mouseDoubleClickEvent o wheelEvent.

La reimplementación de la clase quedaría de la siguiente forma:
GraphicsView::GraphicsView(QWidget *parent) : QGraphicsView(parent) {
/* Aquí se coloca todo el código necesario para la creación e
inicialización del widget */
}

/* Redefinición del método mousePressEvent para tomar las coordenadas x e y del
ratón y almacenarlas en las variables enteras xRaton y yRaton respectivamente */

void GraphicsView::mousePressEvent(QMouseEvent *event){
int xRaton = event->pos().x();
int yRaton = event->pos().y();

//emitir la señal mousePressed
emit mousePressed(xRaton, yRaton);
}

Para utilizar esta subclase solo debemos instanciarla y conectar la señal mousePressed a un slot de nuestra preferencia, por ejemplo:
GraphicsView *visor; //Instanciamos un puntero a un elemento GraphicsView
visor = new GraphicsView(this);

connect(visor, SIGNAL(mousePressed(int, int)), this, SLOT(slot_prara_manejar_raton(int, int)));

Con esto tendremos un QGraphicsView que soporta eventos de ratón :D

NetBeans con C++ y Qt

NetBeans es un IDE que aparte de ser gratuito y open-source es muy completo. Lo he usado para varios proyectos que he desarrollado en Java y nunca me ha dejado mal.

Pero ¿qué pasa si queremos esa funcionalidad para programar en C++ usando las librerías gráficas de Qt? Pues solo hace falta seguir estos sencillos pasos y tendremos a NetBeans configurado como IDE para C++/Qt. Esta explicación se hará bajo un sistema operativo GNU/Linux y suponiendo que ya tenemos el NetBeans instalado (sino puede visitar la página de NetBeans, descargarlo e instalarlo).

Configuración del Editor
  1. Instalar el plugin para C/C++: Vamos al menú Tools->Plugins, en la pestaña Available Plugins buscamos el de C/C++, lo marcamos y hacemos clic en instalar.



    Luego hacemos clic en Next, aceptamos la licencia y comenzará la descarga del plugin



  2. Incluir las librerias de C++ y Qt: Para esto vamos al menú principal, en Tools->Options y nos ubicamos en la pestaña Code Assistance.



    Aquí debemos agregar las siguientes rutas para que el editor reconozca las librerias de C++

    /usr/include/c++/4.2
    /usr/include/c++/4.2/i486-linux-gnu
    /usr/include/c++/4.2/backward
    /usr/local/include
    /usr/lib/gcc/i486-linux-gnu/4.2.3/include
    /usr/include

    Y estas otras para que reconozca las librerias de Qt

    /usr/include/qt4
    /usr/include/qt4/Qt
    /usr/include/qt4/QtCore
    /usr/include/qt4/QtGui
    /usr/include/qt4/QtSql
    /usr/include/qt4/QtNetwork

    Si está usando un sistema operativo distinto de GNU/Linux debe buscar el equivalente de estas rutas.

Si todo ha salido bien al hacer clic en el menú File->New Project deberíamos tener una ventana como la que se muestra a continuación, donde se observa claramente la nueva opción de C/C++ en las categorías de proyectos.



Configuración del Proyecto

Con lo que hemos hecho hasta ahora NetBeans sabe como crear, compilar y ejecutar un proyecto en C/C++ e incluso sabe dónde están las librerías estándar de C/C++ y Qt, pero aún no tiene idea de cómo compilar y ejecutar una aplicación para Qt.

NetBeans usa un archivo Makefile para cada proyecto (generado automáticamente) donde se encuentran las reglas para la compilación. Las aplicaciones Qt no usan las mismas reglas que las aplicaciones C/C++ estándares, así que la solución para esto la tenemos en estos sencillos pasos

  1. Generar el Makefile: Debemos generar nuestro propio Makefile indicándole a NetBeans las reglas para compilar nuestros proyectos Qt. Las aplicaciones Qt se compilan de la siguiente forma:

    qmake -project (para generar el proyecto, es decir el archivo .pro)
    qmake (para generar el Makefile)
    make (para compilar la aplicación usando el Makefile de arriba)


    Es decir, solo tenemos que agregar las dos instrucciones con qmake antes del make correspondiente. Sin embargo aquí se presenta un problema, NetBeans trabaja con un archivo Makefile y qmake trabaja con otro archivo Makefile, ambos son diferentes pero con el mismo nombre. Si compilamos el proyecto de esta forma el Makefile generado por qmake sobreescribirá al Makefile del NetBeans y tendremos que estar reescribiendo este archivo cada vez que queramos generar el proyecto. Para evitar eso basta con hacer que qmake genere su archivo con otro nombre, eso lo logramos agregando la opción -o al qmake. El nuevo Makefile del Netbeans (el único Makefile que debería queda a este punto) podría ser algo como:

    # build
    build: QMake
    make -f QMakefile

    # clean
    clean: QMake
    make distclean -f QMakefile
    rm *.pro -f
    rm QMakefile -f

    # all
    all: build

    QMake:
    qmake -project
    qmake -o QMakefile

    Nota: Antes de cada instrucción DEBE ir un tabulador.

    En el código anterior se nota claramente la definición de la regla QMake, que se encargará de manejar todo lo referente al qmake, además pasamos el parámetro -o al qmake para que genere un archivo de nombre QMakefile y no sobreescriba el Makefile de NetBeans. En el build se llama a la regla QMake (para que qmake genere el .pro y el QMakefile) y luego se hace el make del QMakefile, en el clean llamamos a la regla QMake (para que qmake limpie todo), hacemos la limpieza con make y luego borramos el .pro y el QMakefile para asegurarnos de que se crearan nuevamente la próxima vez que generemos el proyecto

  2. Especificar la ruta del ejecutable: NetBeans ubica los ejecutables en una ruta que depende de la forma en la que generamos el proyecto (Debug o Release) pero qmake coloca el ejecutable en la misma ruta donde se encuentra el proyecto (.pro). Para lograr que NetBeans pueda ejecutar nuestra aplicación debemos especificar la ruta en la que se encuentra nuestro ejecutable. Para ello vamos a las propiedades del proyecto (en la ventana de proyectos hacemos clic sobre el nombre de nuestro proyecto y luego clic derecho -> Properties). Acá buscamos la opción Linker->General y editamos el atributo Output; solo debemos colocar el nombre de la carpeta del proyecto (con mayúsculas y minúsculas)


Con esto ya pueden disfrutar de un completo IDE para C/C++ y Qt.

Guia Básica HTML + PHP

sábado, julio 12, 2008

Esta guía de HTML+PHP la he desarrollado para un curso que dicté hace un mes aproximadamente y hoy he decidido publicarla. Es una guía rápida para todos los que deseen iniciarse en el mundo de la programación web y por ser básica no profundiza mucho en algunos tópicos; es por esto que recomiendo complementarla con otras fuentes de información más detalladas y especificas según sea el caso.

La guía consta de una primera parte basada en HTML (o mejor dicho XHTML, pues se sigue ese estándar rigurosamente), una segunda parte introductoria a PHP y una tercera parte donde se explica como interactuar con ambos, HTML y PHP.

Puede descargar la guía en formato PDF aquí

Cualquier correción, comentario o sugerencia será bien recibido