Generador de sudokus (9x9)

2010/03/13




Como siempre, solamente el algoritmo y la salida estándar. No hay más interfaz por ahora. Trabajaré en ello en cuanto pueda.

Código aquí.

Conway's game of life

2009/12/07
He aquí un programa muy famoso y muy simple: el juego de la vida. Para quien no lo conozca, comience a leer por aquí.






El juego de la vida es un gran ejemplo del comportamiento emergente -un tema muy interesante, por cierto-. Si es la primera vez que se ve y si no se han asimilado los conceptos probablemente no tendrá mucha gracia, pero una vez que se entiende ¡no se puede dejar de ver!

En el código de más abajo -escrito en C, obviamente (aunque sospecho que no es la mejor decisión, sin embargo)- se puede modificar fácilmente el caracter que representa a las células vivas al igual que el caracter que representa a las células muertas. Asimismo, es posible modificar las dimensiones del "tablero" sin mayor esfuerzo. Sin embargo, está limitado a los patrones que se codifiquen señalando manualmente ciertos puntos en una matriz (arreglo de arreglos), lo que no es un gran problema si se tiene tiempo para escribir nuevos patrones... Por cierto, descubrir patrones interesantes es una parte realmente divertida del juego.

En cualquier caso, más allá de la torpe implementación que yo haya hecho, invito a quienquiera que se interese por esto a que escriba su propia versión, que juegue a cambiar las reglas y a descubrir la vida.






El código aquí: el juego de la vida.

K&R

2009/12/06
Navegando me encontré con un libro fundamental que, lo juro, nunca he tenido en las manos. Hasta ahora.

Yo conocí C mediante mis apuntes de otros lenguajes y de pequeños manuales en la red -como éste blog-, y de fotocopias de un libro arcaico y poco claro de Herbert Schildt. Pero para conocer el lenguaje sin más esperas, al ritmo que a cada uno le convenga, y sobre todo, explicado por los autores (Ritchie es  un grande entre los grandes de esta ciencia), nada mejor que el libro.






Gracias a la web LuChOeDu, que lo pone al alcance de todos.

La gestación del lenguaje C

2009/07/28

Dennis y Brian trabajaban en una versión de Pascal llamada "A".

Cuando se dieron cuenta de que alguien intentaba crear programas usando A, rápidamente añadieron características crípticas que lo convirtieron en B, BCPL, y finalmente C.

Se detuvieron cuando lograron compilar sin errores la sintaxis siguiente:

for(;P("\n"),R=;P("|"))for(e=C;e=P("_"+(*u++/
8)%2))P("|"+(*u/4)%2);


Visto en The Smoke Sellers.

Estructuras de control

2009/07/21
Bucles: for

En programación, un bucle es una estructura de control que permite que se ejecuten un conjunto de instrucciones repetidamente, según una condición. Si se requieren ejecutar sentencias más de una vez, for u otros bucles son una gran utilidad.

Lo primero que se dice sobre una estructura de control es su forma general. Para for es

for(inicialización; condición; incremento)
{
|||||||sentencia0;
|||||||sentencia1;
|||||||...
|||||||...
}

Ahora: ¿inicialización de qué? ¿Incremento de qué?

La inicialización suele ser la asignación de un valor inicial para una variable que llamaremos "variable de control". El incremento es cuánto cambiará la variable de control para el próximo ciclo. La condición es simplemente una expresión relacional que define cómo y cuándo terminará el bucle. Observe que cada una de las partes que conforman el bucle for son separadas por un punto y coma (;).

Reflexiónelo un momento: sin bucles, la manera de imprimir los números 1 a 500 -por decir algo- sería escribiendo printf() o funciones parecidas ¡quinientas veces! Lo cual, además de poco práctico y nada elegante, será un seguro desastre: lo reto a demostrar que tiene la paciencia necesaria. Empleando for, esa misma tarea se vería reducida a unas cuantas líneas de código, siguiendo estos pasos:

1) Declarar la variable de control como entero. Por ejemplo: int x.
2) Construir la estructura for. Asignarle 1 a x como valor inicial (x=1).
3) Establecer la condición. Por ejemplo, mientras x sea menor o igual que 500, que se ejecuten las sentencias (x <= 500).
4) Definir el incremento. De cinco en cinco (x+=5), de dos en dos (x+=2), de uno en uno... (x++ ó x+=1); como usted lo decida.

for(x = 1; x <= 500; x++) printf(" %d", x);

Nota: expresiones como x+=2 son pequeñas abreviaciones. En este caso, x += 2 es equivalente a x = x + 2 (x igual a sí mismo más dos). No está limitado a la suma o acumulación; también son posibles asignaciones como -=, *=, etc...



Tabla del 11


La instrucción for de C, comparada con sus equivalentes en otros lenguajes, es por mucho más flexible y adaptable, ya que se le puede escribir de muchas maneras: como al trasladar la inicialización fuera de él; obviar el incremento -aunque trasladándolo a otro sitio, de lo contrario provocaría un bucle infinito- o cosas aún más extravagantes: ¡inicializar varias variables en el mismo bucle for!

El siguiente ejemplo es perfectamente válido.

for(x = 0, y = 20; x <= y; x++, y--)
|||||||printf(" %d %d \n", x, y);

Lo que produciría en pantalla la siguiente salida.




Haga sus pruebas.

Estructuras de control

2009/07/20
Condicionales o de decisión: switch

Implícitamente switch manifiesta elegancia. Ya que, una vez que se conoce, uno se da cuenta que es una forma práctica y muy ordenada de evaluar constantes.

Su forma general es

switch(variable) {
|||||||case constante0:
|||||||||||||||sentencias;
|||||||case constante1:
|||||||||||||||sentencias;
|||||||case constante2:
|||||||||||||||sentencias;

||||||||||...

|||||default:
|||||||||||||||sentencias;
}


En primer lugar, switch evalúa una y sólo una variable. Según qué constante esté almacenada en la variable será el "case" cuyas sentencias se habrán de ejecutar.
Si ningún "case" corresponde a la constante de la variable evaluada, y existe "default" -cuyo uso es completamente alternativo: puede o no presentarse-, serán las sentencias de "default" las ejecutadas.

Como verá, su uso es muy simple. Ponga atención al siguiente ejemplo.



Todos los "case" ejecutarán la misma sentencia, sin importar cuál sea el que contenga la constante correcta. En este caso, mientras la variable sea igual a una vocal, los "case" correspondientes retornarán el valor 1, para Verdadero. Si la variable no almacena una vocal, será "default" la culpable de retornar 0.

Ahora, si lo importante fuese evaluar un caracter en particular, habría que recurrir al uso de la sentencia break por cada "case".
break utilizada dentro de cada "case" provoca que el control del programa salga del bloque switch y continúe justo después donde éste acaba. Sin break en cada "case" -como en el ejemplo-, todas las sentencias se ejecutarán.

Repetición simplificada: cada "case" se ejecutará uno detrás de otro, a menos que exista la sentencia break entre ellos.

En programas de sólo texto (como todos los ejemplos mostrados aquí) switch es a menudo empleada para comprobar una entrada en el teclado y ejecutar las sentencias que correspondan; pudiendo llamar a otras funciones y/o procedimientos adecuados. Observe un menú como ejemplo.



Nota: Tratándose de un caracter individual (tipo de dato char) siempre se escribirá en comillas simples: case 'a', case '5', etc.

En el fondo, switch es una escalera if - else if muy ordenada que sólo evalúa igualdades; nunca expresiones relacionales ni lógicas.

Estructuras de control

2009/07/18
Condicionales o de decisión: if

Este tipo de estructuras permiten decidir qué líneas de código se ejecutarán, según una condición concreta. En español, la sentencia if es parecida a la frase "Si... [Condición], entonces... [Resolución]".

La forma más simple de la sentencia es

if(condición) sentencia;

ó

if(condición)
|||||||sentencia;

Cuando se escriba más de una sentencia dentro de la misma estructura deben agregarse llaves de inicio y fin.

if(condición) {
|||||||sentencia0;
|||||||sentencia1;
|||||||sentencia2;
}

Si la condición es cierta, las sentencias se ejecutarán. De lo contrario, el programa continuará justo después del final del bloque if.

En ocasiones es conveniente analizar varias condiciones. Asímismo es conveniente tener una salida o escapatoria para cuando ninguna condición se cumple. Es entonces cuando se emplea la escalera if-else if.

if(condición)
|||||||sentencia;
else if(condición)
|||||||sentencia;
else if(condición) {
|||||||sentencia0;
|||||||sentencia1;
|||||||sentencia2;
}
else if(condición)
|||||||sentencia;
else |||||||||||||||||||||//Se cumplirá sólo si las anteriores son falsas
|||||||sentencia;|||||

Una condición es una expresión lógica; con operadores relaciones y lógicos, tal como 5 <= 2 y 42 == 20 + 20 + 2, falso y verdadero, respectivamente.

Las condiciones se evalúan de arriba a abajo. Cuando una condición sea cierta se ejecutan las sentencias asociadas a ella y se ignora el resto de condiciones. Si ninguna es cierta, y existe 'else', será 'else' la que se ejecute. Si no hay 'else' y todas las condiciones fallan, no ocurrirá ninguna acción.

Ejemplos:







Encuentre las diferencias.