La cita del día
6/06/2008“Dios usó fork() para crear a Eva”
Vía | Bash.org
Archivo de artículos en la categoría "Programación"
Ir al inicioUna propiedad de Subversion que viene bien cuando tienes muchos archivos ajenos a tu repositorio mezclados con tu código, es el svn:ignore.
Al hacer un svn status en lugar de tener un resultado con un montón de archivos inservibles ..
$ svn status calc M calc/button.c ? calc/calculator ? calc/data.c ? calc/debug_log ? calc/debug_log.1 ? calc/debug_log.2.gz ? calc/debug_log.3.gz
.. puedes tener un resultado con solo los archivos que te interesan filtrando los indeseados, solo tenemos que agregar la propiedad ignore al directorio calc ..
svn propedit svn:ignore calc
.. esto te abrirá un editor donde agregas un patrón (ojo, no es una expresión regular) que en nuestro ejemplo ignorara a todo menos a archivo data.c
calculator
debug_log*Y listo, ahora el resultado de svn status solo es lo que nos importa.
$ svn status M calc M calc/button.c ? calc/data.c
Enlace | SVN Book
El Proyecto Euler es una serie de problemas de programación, si quieres enterarte de que va esto, lee la introducción.
Cada nuevo termino en la secuencia de Fibonacci es generada agregando los dos términos previos. Comenzando con 1 y 2, los primeros 10 términos serán:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …
Encuentra la suma de todos los términos pares en una secuencia que no sobrepase los 4 millones.
Para resolverlo de la forma bruta, hay que construir la secuencia de Fibonnaci solamente agregando una condición donde vamos agregando una sumatoria de los números pares, esa verificación es donde muy probablemente se pueda optimizar esto. Mañana salgo de viaje, hasta fines de la siguiente semana revisare que se pudo hacer.
Por cierto, hubiera jurado que el problema antes estaba escrito con el límite de 1 millón, así tenía guardada la solución, me pregunto ¿porque lo habrán cambiado? por lo pronto el siguiente que haga sera completamente nuevo, los dos primeros ya los había resuelto cuando me registre a la página.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <stdio.h> main() { int sum = 0, a = 1, b = 1, c = 0; while ( c < 4000000 ) { c = a + b; a = b; b = c; if ( c % 2 == 0 ) { sum += c; } } printf("resultado: %d\n", sum); return 0; } |
Lo mas costoso de esta solución es la comprobación de que los números sean pares, y revisando otras soluciones hay muchas formas de evitar esta comprobación.
Como bien notaron Michoacano y Xiam, resulta que si revisamos la secuencia, podemos notar que cada tercer número es par y ya sabiéndolo de antemano nos podemos evitar la comprobación y sumar solo cada tercer número.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <stdio.h> main() { int sum = 0, a = 1, b = 1, c = a + b; while ( c < 4000000 ) { sum += c; a = b + c; b = c + a; c = a + b; } printf("resultado: %d\n", sum); return 0; } |
Nuevamente, esto ayudara realmente en rangos mucho mas grandes que el que tenemos.
El Proyecto Euler es una serie de problemas de programación, si quieres enterarte de que va esto, lee la introducción.
Si listamos todos los números naturales debajo de 10 que son múltiplos de 3 o 5, tenemos 3, 5, 6 y 9. La suma de estos múltiplos es 23.
Encuentra la suma de todos los múltiplos de 3 o 5 debajo de 1000.
Este problema lo he visto como de los ‘recomendados’ para poner en las entrevistas para trabajo, simple y rápido, te dice claramente las 3 condiciones a evaluar.
El operador % regresa el residuo de una división, por lo que podemos iterar de uno en uno hasta el límite superior (1000) y verificar si cada número es perfectamente divisible (el residuo es 0) entre 3 o 5, entonces lo podemos almacenar.
Resuelto en C.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <stdio.h> main() { int sum = 0, i; for ( i = 1; i < 1000; i++ ) { if ( (i % 3 == 0) || (i % 5 == 0) ) { sum += i; } } printf("El resultado es: %d", sum); } |
Comparando con resultados del Proyecto Euler, si bien la solución de fuerza bruta que hice no esta mal, si la pregunta exigiera un limite con cantidades grandes no es eficiente hacer un loop comparando resultado por resultado, sino que es mejor calcular las operaciones por separado.
La suma de números divisibles por 3, la suma de números divisibles por 5 y restando finalmente los números divisibles por 15 que sino tendríamos los divisibles comunes de 3 y 5 contados 2 veces. Se puede evadir por completo cualquier loop si utilizamos progresiones aritméticas.
Para poner un poco en contraste, haciendo benchmark (utilizando gprof) de mi solución para el limite de 1 billón (si si, un uno seguido de 9 ceros), este laptop tarda 15.68 segundos.
En cambio la siguiente versión (versión de sandippal en el foro) que utiliza este principio, tarda menos de .01 segundo, ¿bastante no?.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <stdio.h> #define NUM 999999999 main() { unsigned long long mult3 = NUM / 3; unsigned long long mult5 = NUM / 5; unsigned long long mult15 = NUM / 15; unsigned long long sum3, sum5, sum15; sum3 = 3 * mult3 * (mult3 + 1) / 2; sum5 = 5 * mult5 * (mult5 + 1) / 2; sum15 = 15 * mult15 * (mult15 + 1) / 2; printf("resultado: %lld\n", sum3 + sum5 - sum15); } |
Gracias en especial al comentario de Xiam, grande su explicación.
¿Que es el Proyecto Euler?
El Proyecto Euler es una serie de retadores problemas de matemática/programación que requerirán mas que un poco de conocimientos de matemáticas para resolver. Aunque las matemáticas te ayudarán a tener métodos elegantes y eficientes, el uso de la computadora y habilidades de programación son requeridos para resolver la mayoría de los problemas.
Desde hace tiempo he querido avanzar con ellos y mi desidia no me ha dejado, así que ahora publicaré los problemas que vaya resolviendo (si, uno por uno) y de paso me doy motivación extra.
También es una perfecta oportunidad para que la vasta fauna del internet pueda corregir mi imperfecta manera de programar, así que cualquier corrección no duden en hacerla, mientras mas me equivoco mas aprendo.
Algunas cosas que notar:
En un canal de IRC, hoy una persona me hizo recordar un problema que tuvimos hace un par de semanas en la oficina porque los datos en JSON que regresaba una web, mágicamente desaparecían aun cuando antes estaba funcionando.
En ambos casos fue el mismo error, no se tenia contemplado que los datos enviados fueran a crecer demasiado eventualmente, y como X-JSON utiliza los headers de HTTP, tiene un tamaño limitado.
Yo realmente no le veo el punto de su existencia, ¿enviar estados de una página? ¿mensajes cortos? Para eso mejor utilizar headers correctos de HTTP y cualquier tipo de datos por el cuerpo de la página como fue pensado desde el principio, la confusión que puede crear es mayor que el beneficio.
Si lo dejas a mi opinión: No lo uses, evítalo.
Este año viene por primera vez el Google Developer Day a la Ciudad de México, mas específicamente al centro Banamex.

Para cualquier interesado en desarrollo web es una conferencia atractiva, es todo un dia de conferencias y talleres de código sobre herramientas de Google, incluyendo “OpenSocial, Android, Google Web Toolkit, Google Gears, Mapas/KML y más”.
El evento es gratis, asi que no hay excusa, a mi me ha convencido Luis (a.k.a. GoogleFan) de registrarme, así que estaré por el DF el 23 de Junio.
Tanto como no se debe de usar un Model dentro de un Component, tampoco se debe de usar un Element dentro de un Helper, aun así, si tienes una situación especial donde debes de hacerlo, lo puedes lograr de la siguiente manera.
1 2 | $vista = ClassRegistry::getObject('view'); $vista->renderElement('nombre_elemento'); |
CakePHP te pone las reglas (y para tu propia sanidad, deberías de seguirlas), pero no te limita a ellas.
Un archivo XSD (XML Schema Definition) contiene una serie de patrones que un archivo XML debe de cumplir para ser considerado ‘valido’ de acuerdo a ese esquema.
Si estas en linux, puedes utilizar el parser de XML de manera muy sencilla y ahorrarte el tener que perderte entre las decenas de opciones para validación.
xmllint –schema esquema.xsd archivo.xml
Si por alguna razón no puedes usar este útil comando, la W3 y XML.com sugieren muchas (pero muchas) herramientas que nos sirven, y sino siempre esta Don Google que no se raja.
Leyendo Quest’s Blog, me encontré un par de artículos de Perfection Kills, que dan unos tips acerca del uso básico de Prototype.
El primero en especial me parece muy útil, a pesar de que son cosas muy simples son errores que todos cometemos al principio, ¿Seamos sinceros, que tantos se chutan toda la documentación antes de empezar a programar?
Me servirá de recordatorio así que me he tomado la libertad de publicarlo:
Modo Incorrecto
1 | document.getElementById('foo') |
Modo Correcto
1 | $('foo') |
El operador $ es lo mas esencial de Prototype, de ahí viene toda su magia, utilizalo!
Modo Incorrecto
1 2 | var woot = document.getElementById('bar').value var woot = $('bar').value |
Modo Correcto
1 | var woot = $F('bar') |
El operador $F es un gran atajo para obtener valores de elementos.
Modo Incorrecto
1 2 | $('footer').style.height = '100px'; $('footer').style.background = '#ffc'; |
Modo Correcto
1 2 3 4 5 6 | $('footer').setStyle( { height: '100px', background: '#ffc' } ) |
Olvidate de problemas de bugs sobre diferentes navegadores si utilizas el metodo setStyle()
Modo Incorrecto
1 | $('tusuperelemento').innerHTML = 'algun contenido' |
Modo Correcto
1 | $('tusuperelemento').update('algun contenido') |
Podras decir que es casi la misma, pero no opinaras lo mismo cuando necesites concatenar funciones.
Modo Incorrecto
1 | new Ajax.Request('ninja.php?weapon1=foo&weapon2=bar') |
Modo Correcto
1 2 3 4 5 6 7 8 9 | new Ajax.Request('ninja.php', { parameters: { weapon1: 'foo', weapon2: 'bar' } } ) |
Escribe código limpio, tu cerebro te lo agradecerá.
Modo Incorrecto
1 2 3 4 5 6 7 8 | new Ajax.Request('blah.php', { method: 'POST', asynchronous: true, contentType: 'application/x-www-form-urlencoded', encoding: 'UTF-8', } ) |
Modo Correcto
1 | new Ajax.Request('blah.php') |
Todos esos parámetros ya son defaults, ¿Para que repetirlos?.
Modo Incorrecto
1 | Event.observe('myContainer', 'click', doSomeMagic) |
Modo Correcto
1 | $('myContainer').observe('click', doSomeMagic) |
Es mas fácil concatenar si escoges el segundo, pero aquí es cuestión de gustos, escoge el sabor que mas te guste.
Modo Incorrecto
1 2 3 4 5 | $$('div.hidden').each(function(el) { el.show(); } ) |
Modo Correcto
1 | $$('div.hidden').invoke('show') |
Invoke es muy útil, piensa en el como en un atajo cuando necesitas asignar valores iguales a todos tus elementos sin necesidad de iterar sobre ellos.
Modo Incorrecto
1 2 3 4 5 | $$('div.collapsed').each(function(el) { el.observe('click', expand); } ) |
Modo Correcto
1 | $$('div.collapsed').invoke('observe', 'click', expand) |
Y también puede ser usado para manejo de eventos, muy practico!
Modo Incorrecto
1 2 | $$('input.date').invoke('observe', 'focus', onFocus); $$('input.date').invoke('observe', 'blur', onBlur); |
Modo Correcto
1 2 3 | $$('input.date') .invoke('observe', 'focus', onFocus) .invoke('observe', 'blur', onBlur) |
¿Para que abusar del operador $$ dos veces si podemos concatenar?
Modo Incorrecto
1 2 3 4 5 6 | $('productTable').innerHTML = $('productTable').innerHTML + '<tr><td>' + productId + ' ' + productName + '</td></tr><tr><td>' + productId + ' ' + productPrice + '</td></tr>' |
Modo Correcto
1 2 3 4 5 6 7 8 9 10 11 | var rowTemplate = new Template('<tr><td>#{id} #{name}</td></tr><tr><td>#{id} #{price}</td></tr>'); $('productTable').insert( rowTemplate.evaluate( { id: productId, name: productName, price: productPrice } ) ) ) |
Este tip en especial es una joya, con Prototype podemos hacer templates, evitando de esta manera enormes plastas de código. Me confieso culpable de no haber utilizado esto antes.
Enlace | How well do you know prototype