lunes, 29 de diciembre de 2008

VMware 1.0.8-126538 en kernels nuevos, una odisea

Actualizacion: los problemas de vmmon descriptos en este articulo y algunos mas se resolvieron en el patch que publico y describo en este post

Desde hace unas semanas que me hice un tiempo e instale fedora 10 con kde4 y toda la magia, pero llego el momento en que necesite virtualización, ahí empezó una entretenida historia (entretenida ahora que termino bien :D )
Si algunos de los que están leyendo esto comparten la experiencia de haber intentado instalar la ultima versión de VMware en uno de los últimos linux con el kernel 2.6.27.9 o alguna versión parecida, (encontré foros de personas que decían que este mismo problema pasa también en el ultimo ubuntu, seguro en otras distribuciones tambien ), habrán leído en la pantalla unas groserías particulares, cuando ejecutaron el famoso vmware-config.pl:

"/tmp/vmware-config1/vmmon-only/./include/compat_semaphore.h:23:27: error: asm/semaphore.h: No such file or directory"
"/tmp/vmware-config24/vmmon-only/linux/driver.c:153: error: se especificó el campo desconocido ‘nopage’ en el inicializador"

y asi...

No aguante mas y entre a meter mano en el codigo, primero lo del semaphore.h, no era complejo, simplemente cambiaron al .h de lugar, ahora esta en linux/semaphore.h en lugar de asm/semaphore.h en el nuevo kernel:




#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
#include "asm/semaphore.h"
#else
#include "linux/semaphore.h"
#endif



respecto a lo de nopage, no se bien que significa :(, lo unico que hice fue comentar las dos lineas que causaban problemas:


...

static void LinuxDriverPollTimeout(unsigned long clientData);

static struct vm_operations_struct vmuser_mops = {
// .nopage = LinuxDriverNoPage
};

struct vm_operations_struct vmuser_locked_mops = {
// .nopage = LinuxDriverLockedNoPage
};

static struct file_operations vmuser_fops;
static struct timer_list tscTimer;

...


Tomar nota de esto ultimo, queda pendiente evaluar el significado de todo eso


Y eso no fue todo, como todo un clásico de la programación C, al corregir errores, el compilador revela los otros errores que antes no se mostraron al no llegar a compilar esas secciones, quedo un desbarajuste en la función smp_call_function, que según el smp.h del kernel, tomaba 3 argumentos, y en driver.c y hostif.c del codigo fuente de vmmon, lo llamaba pasando 4 parámetros, a esto, lo resolvi eliminando el tercer argumento de todas las llamadas a la función smp_call_function ( y compat_smp_call_function, que era un sinónimo en ese código ). Elimine el tercer parametro porque en la definición de la funcion smp_call_function en el código del kernel mas viejo era el "retry" el tercer parámetro extra que había demás en relacion al nuevo



// version nueva EN linux/smp.h

/*
* Call a function on all other processors
*/
int smp_call_function(void(*func)(void *info), void *info, int wait);

// version vieja en linux/smp.h

/*
* Call a function on all other processors
*/
int smp_call_function(void(*func)(void *info), void *info, int retry, int wait);



Por ultimo, queda una llamada a kill_proc en linux/hostif.c, que segun el compilador no existe un kill_proc definido, ahi simplemente comente la linea :p

Y por ultimo, al compilar vmnet, surge el mismo problema del semaphore.h, la solución es exactamente la misma que con la compilación del otro modulo

Al final funciono todo, al punto que compilo todo, pude configurar todo lo que necesite y pude crear y bootear una maquina virtual, si embargo dos cosas (que habia mencionado antes) quedaron atadas con alambre:

1) el .nopage = LinuxDriverNoPage comentado casi al principio de linux/driver.c
2) el kill_proc comentado casi al final de linux/hostif.c
3) La version del kernel que no supe precisar en el #if que incluye el semaphore.h

Disculpen no haber subido el parche que genere, pero esos últimos dos puntos me parece que quedaron muy truchos y no quiero que cause problemas tratándose este código que toque de nada mas y nada menos que de módulos del kernel

Lo probe un poco, y al parecer el cambio del kill_proc genera algunos problemas, ya que al correr la mayoria de las maquinas virtuales, vmserverd termina por un error causado en el kernel,

con este problema:

Kernel failure message 1:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
IP: [<0000000000000000>] 0x0
PGD 12944067 PUD 12942067 PMD 12941067 PTE 0
Oops: 0010 [1] SMP

y con este backtrace:

[] ? HostIF_SetFastClockRate+0xb0/0x137 [vmmon]
[] Vmx86_SetHostClockRate+0xb4/0xc9 [vmmon]
[] LinuxDriver_Ioctl+0x3d3/0x923 [vmmon]
[] ? inode_has_perm+0x5b/0x61
[] ? __dequeue_entity+0x61/0x6a
[] ? remove_wait_queue+0x2f/0x39
[] ? file_has_perm+0x83/0x8e
[] LinuxDriver_CompatIoctl+0x2b/0x40 [vmmon]

Fijense que la funcion con problemas, es la que modifique comentando el kill_proc, se resolveria cuando encuentre una implementacion de kill_proc que use las posibilidades de este nuevo kernel

Después de un rato, corregí la función , reemplazando a kill_proc por su equivalente el nuevo kernel, tal como explica en esta pagina , cuando compilo, siguió existiendo el mismo error, buscando por la web, encontré algo acerca de please revert commit 53f1b1433da7eac2607a4...; aparentemente, un chabon hizo un commit, que crashea el kernel cuando cierta función se llama de cierta forma, espero que actualizando el kernel cuando se corrija o patcheandolo pueda solventar este problema

viernes, 26 de diciembre de 2008

Extraccion de direcciones de mail de texto en dos lineas

DISCLAIMER: la siguiente información se difunde solo con fines educativos, el blog de NilClass NO fomenta el spam



# El codigo consta de dos chainings,
# el primero abre el archivo y escribe en el
# (todo el codigo hasta el .write inclusive)

# en el primer chaining

# abre el archivo (File.new( "..." , "w") )
# invoca el metodo write

# en el segundo chaining

# abre el archivo, para lectura
# hace un read al archivo, para leer todo su contenido
# hace un split, usando como divisor la expresion regular
# la expresion regular especifica que matchee todo lo que
# no sea ni letra minuscula ni letra mayuscula ni numero
# ni esos caracteres que pueden tener las dir. de mail
# despues el chaining hace un select de los strings que contienen
# el caracter "@"
# y por ultimo, efectua un join uniendo todas las cadenas
# con el caracter de salto de linea (\n) de por medio

ary = File.new("rawtext.txt").read.split(/[^a-zA-Z0-9@._-]/)
File.new("mails-parsed.txt","w").write ary.select{ |x| x =~ /@/ }.join("n")

# nota: esta claro que pude haber hecho todo en una sola linea
# pero lo separe en dos para que quepa en la columna del post

lunes, 22 de diciembre de 2008

Conexion a bases de datos mysql via ruby

Por razones que no vienen al caso encontré e instale una librería para ruby que permite conectarse a los motores de bases de datos mysql, la misma la pueden encontrar en http://www.tmtm.org/en/ruby/mysql/, la libreria se puede usar mas o menos asi:



require "gramas"
require "mysql"
my = Mysql::new("localhost", "username", "password", "database")
res = my.query("select name,surname from users")
res.each do |row|
col1 = row[0]
col2 = row[1]
end

martes, 16 de diciembre de 2008

Como mantener una lista de subclasses en una clase

Definiendo el método de clase inherited, se pueden hacer muchas cosas cuando se hereda una clase, entre ellas esto:


# defino un modulo para agrupar los métodos que se agregan a las clases
module SubclassesRegister
def subclasses
if @subclasses == nil
@subclasses = []
end

@subclasses
end
end

# la clase principal, la que implementa la funcionalidad de registrar las subclases
class RegisteredClass

def self.inherited(x)

# se le agregan los metodos para que mantenga la lista de superclases ( a la superclase de x)
x.superclass.extend SubclassesRegister unless x.superclass.include? SubclassesRegister

# cuando alguna clase hereda de esta, se registra la subclase (si la superclase no es esta)
if x.superclass != RegisteredClass
self.register_subclass(x)
end
end

def self.register_subclass(subclass)

superclass = subclass.superclass
print "registered #{subclass} as subclass of #{superclass}\n"

# agregar la clase subclass a la lista de subclases de su superclase
superclass.subclasses << subclass
end
end

class Animal < RegisteredClass
def self.enu
# puedo obtener las subclases con solo usar el metodo "subclasses"
print "subclases de Animal: #{subclasses.join("; ")}\n"
end
end

class Perro < Animal
def self.enu
# cualquier clase de la jerarquia que extienda directa o indirectamente de RegisteredClass
# puede obtener la lista de sus subclases
print "subclases de Perro: #{subclasses.join("; ")}\n"
end
end

class Terrier < Perro
end

class Dogo < Perro
end

class Gato < Animal
end


Animal.enu
Perro.enu




Espero que les haya sido de utilidad

lunes, 15 de diciembre de 2008

¡¡¡ Aleluya !!!, consegui el Rubik original


Al principio crei que era un sueño, pero lo consegui, con empaque original y todo, en pocas palabras, el de la foto de la derecha
Por si no lo sabian, en Argentina, durante un tiempo importante no hubo distribuidor oficial del cubo Rubik, y ahora es muy dificil de conseguir, y lo consegui.
El cubo es mucho mas maleable que cualquier "imitacion" que se puede conseguir practicamente en cualquier negocio, aparentemente el plastico del que se componen las piezas tiene mayor calidad y por lo tanto dura mas; y los stickers tambien, en el mismo tiempo de uso que en los otros cubos los stickers empezaban a perder el color, este sigue aparentando que no se uso !!!, es increible.
Como bonus tambien me compre uno de 4x4 (code name: The Revenge of Rubik), el de la otra foto



viernes, 12 de diciembre de 2008

La guerra de cookies

No se como describirlo, no se sabe como empiezo, en un instante dado, salto uno diciendo
"Quiero editar cookies", y el otro dijo "No se puede, estan en el server", entonces , el otro dijo... Mejor pongo un guion:

-

Lo siguiente ocurre entre las 12:00 pm y las 13:00 pm

Matt: Quiero setear una cookie
Diego: No se puede, esta en el server
Caco: Podes usar javascript.cookie
Matt: Solo setea localhost, quiero setear para ese host
Diego: No tiene sentido setear una cookie, el server no la va a aceptar, el server genera la cookie
Matt: Quiero setear una cookie en el browser
Robert: Miren esto
Diego: Espera
Matt: Espera
Diego: No tiene sentido setear una cookie, el server no la va a aceptar, el server genera la cookie
Matt: ¡¡¡Quiero poner la cookie!!!
Robert: Miren esto
Diego: Espera
Matt: Espera
Diego: No tiene sentido setear una cookie, el server no la va a aceptar, el server genera la cookie
Matt: ¡¡¡Quiero poner la cookie!!!
Robert: Miren esto
Diego: Espera
Matt: Espera
Diego: No tiene sentido setear una cookie, el server no la va a aceptar, el server genera la cookie
Gise: BBAAAAAAAAAAAAASTAAAAAA!!!
Matt: ¡¡¡Quiero poner la cookie!!!
Diego: No tiene sentido setear una cookie, el server no la va a aceptar, el server genera la cookie
Matt: ¡¡¡Quiero poner la cookie!!!


for i in (1..3000)
print "Diego: NO se puede\n"
print "Matt: SI se puede\n"
end


Robert: Miren esto (mostrando el cuadro de agregar una cookie )
Diego: Espera
Matt: Espera. A ver...

Robert: Usa ADD N EDIT COOKIES para Firefox

Matt: Robert encontró lo que quería desde el principio
Diego: ¿eso era?


end

miércoles, 10 de diciembre de 2008

He descubierto una funcion no documentada en dos sistemas operativos: AltTAB ReversO

El fin de semana descubri algo muy loco. ¿ Alguno de ustedes se encontró altabulando en decenas de ventanas en el escritorio , y de repente se dan cuenta de que se pasaron la que querían, y por lo tanto se ven obligados a dar toda la vuelta ?. La solucion esta a milímetros del meñique, mientras mantienen apretada la tecla ALT, presionen y mantengan apretada la tecla SHIFT tambien, cuando presionen TAB, altabulearean en sentido reverso !!
Lo curioso de esta técnica, es que funciona en los escritorios de Windows, en Kde y Gnome (si algún usuario de MacOS esta leyendo esto, por favor que deje un comentario acerca de si esto también sirve en el mundo bizarro) ; no solo eso, también funciona en el navegador Firefox para las pestañas (en este caso la tecla para cambiar de pestañas es control+tab, pero también sigue siendo el poderoso SHIFT, el agente reversor de la funcionalidad )

Esto fue todo por hoy, espero que les haya gustado, chau

Lo que pasa cuando no se usan "captchas" y como te obligan a pagar linux

Miren todos los comentarios que dejaron de este articulo:


http://www.todo-linux.com/modules.php?name=News&file=article&sid=416


Hablando del tema en cuestion, espero que los "SGAE" locales ( i'am from Argentina ), no sean tan "creativos"

lunes, 8 de diciembre de 2008

Hacer split de strings con expresiones regulares

Imaginense el caso:


str = "hola como estan chau"
str.split.each do |x|
print x,"\n"
end


Dara como resultado:

hola
como
estan
chau

Pero si tuvieramos (agregando signos de puntuacion entre las palabra):


str = "hola,como estan;chau"
str.split.each do |x|
print x,"\n"
end


La salida seria:

hola,como
estan;chau

Y en la mayoria de los casos, eso no es lo que buscamos, para obtener lo que queremos (separar todas las palabras, sin importar que las dividan), podemos recurrir a lo siguiente:


str = "hola,como estan;chau"
str.split(/,|\s|;/).each do |x|
print x,"\n"
end


O mejor aun

str = "hola,como estan;chau"
str.split(/\W/).each do |x|
print x,"\n"
end


Eso retorna las cuatro palabras separadas. El argumento /,|\s|;/ que se le paso a split , es una expresion regular que matchea el caracter coma, el punto y coma o espacio indicandole que tiene que tomar cualquiera de estos como separador, en el segundo caso, la expresion regular indica que tome como separador cualquier caracter que no sea alfanumerico. Como imaginaran, esto es bastante util para extraer facilmente palabras de textos webs, txts, etc...

Espero que les haya gustado, chau

domingo, 7 de diciembre de 2008

El cyber de los cartoneros ocupas

Hoy fue uno de esos dias raros, en los que sali a la calle en busca de un cyber con internet, porque en casa se descompuso internet, y necesitaba enviar este post. Lo cierto que tras cuadras de recorrido, llegue al unico que encontre, el tipico negocio locutorio-kiosko-cyber-psicologo-verdulero, entre preguntando cuanto cuesta la hora, y me sorprendi al escuchar que dijo "setenta y cinco centavos", (precios como este solo los vi en la epoca pre-apocaliptica del 1 a 1). Lo cierto es que le di para adelante, y empuñando en alto mi usb, me dijo "usb anda a la 6".
Y en la seis, y en todas las demas, Windows 98 Edicion Cartonero, con buscaminas y solitario 2D !!!, con Intenet Exploder 6.0, msn 6.0 y mIRC version 0.01beta (este ultimo es falso, ni siquiera habia mIRC) todo un emergente mundo retro. Aun con todo esto, me quede ya que no habia otra, y tenia que lanzar urgente un tar.gz al cyber-espacio, cuando me disponia a colocar el pen-drive, observe pasmado que el gabinete AT , ¡¡¡estaba pidiendo EUTANASIA!!! por poco y tenia una entrada para floppy 5 1/4 ( se ve que se lo sacaron para poner un 3 1/2 en su lugar, que es mas moderno ).
El monitor por supuesto, a 640x480, porque era lo maximo que soportaba. En una carpeta que estaba por ahi, en una esquina, estaba el magnifico instalador del IE 6.0 (ya que win98 venia con IE 5.0 ), todo un reto, hacer que funcione algo, ahi, cualquier programa que traia en el usb, anunciaba "Windows 2000 or higher is needed for install..."
El cyber hecho por cartoneros ocupas, se hizo con toda la intencion (de hacer plata facil) recuperando maquinas DE LA BASURA, y por extension, instalando sistemas operativos DE LA BASURA TAMBIEN, pero a ese lugar no vuelvo, aunque me paguen 75 centavos la hora a mi en lugar de que yo les tenga que pagara ellos.
Aclaracion: no tengo nada en contra de los cartoneros, siempre y cuando no pongan cybers a cuadras del congreso

Programa para generar imagenes "flasheras"

Hoy estuve navegando por la web, y me tope con un articulo de un blog, el cual promovia y ensañaba el uso de un programa llamado apophysis. Esta aplicacion, servia para generar imagenes fractales, como esta:



En el primer link que inclui en este articulo hay muchos mas ejemplos, no los inclui todos en este post porque se ve que tienen alta resolucion y ocasionan gran cantidad de trabajo al browser :p
Hasta el proximo articulo, van a conocer mis conclusiones acerca de esta herramienta cuando la pruebe

viernes, 5 de diciembre de 2008

4x3x2 = FRACTURA EXPUESTA DE PULGAR

A mi sinceramente no se me hubiera ocurrio algo asi. Aparentemente el que manipula el paralelepipedo ortogonal rubik (no es un cubo, en terminos estrictos) se fracturo el pulgar jugando con eso (aun asi, sigue)

el NilClass

Vean el siguiente ejemplo



# un array asociativo
array = { 1 => "Robert", 2 => "Ruby" }

# imprimir las longitudes de las cadenas del array
(1..3).each do |i|
# CUIDADO al tratar de procesar el string numero 3, se generara un error
# "undefined method 'length' for nil:NilClass (NoMethodError)"
print "longitud de la cadena #{i}: #{array[i].length}\n"
end



el elemento 3 del array asociativo, era un nil, por lo tanto devolvio ese error, pero, trato de invocar el metodo al objeto nil, que es de tipo NilClass, eso significa que se puede definir el metodo en el objeto



# un array asociativo
array = { 1 => "Robert", 2 => "Ruby" }

# antes, puedo definir el metodo length del nil
def nil.length
0
end

# imprimir las longitudes de las cadenas del array
(1..3).each do |i|
# Esta vez no genera ningun error
print "longitud de la cadena #{i}: #{array[i].length}\n"
end


Tambien es valido definir el metodo en el NilClass, por lo que conozco es lo mismo (NilClass es una clase cuya unica instancia es nil)


# un array asociativo
array = { 1 => "Robert", 2 => "Ruby" }

# antes, puedo definir el metodo length en la clase NilClass
class NilClass
def length
0
end
end

# imprimir las longitudes de las cadenas del array
(1..3).each do |i|
# Esta vez no genera ningun error
print "longitud de la cadena #{i}: #{array[i].length}\n"
end




En definitiva, para explicar lo ocurrido, nil es el objeto referenciado por las variables que no referencia a nada, es algo parecido al hecho de conceptualizar una entidad que creo la parte del universo que no fue creada por nadie, o la definicion del "eter" gas que conduce las ondas de luz que existe en todo el espacio exterior , donde se suponia que hay "vacio"
A diferencia de lenguajes como java , o .net, los cuales admiten variables que no hagan referencia a *nada*, dando lugar a "NullPointerExceptions", en ruby esto no tiene sentido, por lo tanto no pueden existir variables que apunten a la nada, si existen variables que apuntan al objeto nil, que representa a la nada, lo cual nos lleva a que tanto los lenguajes mencionados anteriormente se rigen por el mismo principio: la nada en un contexto tan abstracto, tiene el mismo nivel de tangibilidad que cualquier algo (como clases, metodos y otras cosas), java define a esa nada como un "null", y ruby como un "nil".
La diferencia que si existe, es que en java esa representacion de nada, es "especial", es algo mas, una cosa aparte; en cambio, en ruby, la representacion de la nada, es nil, que tambien es un objeto ya que en ruby todo es un objeto, por que lo "especial", se admite en la menor medida posible, ya que añade gran complejidad a esto.
Al ser la representacion de nada un objeto como los demas, admite todo lo que los objetos admite: metodos, mas instancias, estado, etc..., si esto tiene sentido o no definira el programador, si quiere usar estas funcionalidades o no, se puede decir tanto que no tiene sentido que la nada tenga "funcionalidades" como tambien se puede decir que no es correcto que la nada no pueda ser tratada como un concepto al igual que los demas, como las clases, metodos y variables
Espero que les haya sido de utilidad, cerramos con otra exhibicion de nil, menos charla y mas accion:


# ESTO NO SE PUEDE HACER, POR RAZONES ¿OBVIAS?
# atencion: todas las lineas de codigo posteriores dan algun tipo de error

# duplicamos el nil original, ya que es un objeto
# esto no anda, no se puede duplicar el concepto de la nada
# para crear otro concepto, el concepto de nada
# es unico (el patron singleton)
otronil = nil.dup

# instanciamos otro nil usando la NilClass
# no se puede fabricar distintos conceptos de nada
# eso conlleva a la nada (valga la redundancia)
otronilmas = NilClass.new


Ahora algo que funcione



# se le pueden definir los metodos que sean al NilClass
# y tambien variables locales
class NilClass
def initialize
super
@vacio = 4
end

def vacio= (a)
@vacio = a
end
def vacio
@vacio
end
end

nil.vacio = 4
print nil.vacio

Las viscicitudes y la esquizofrenia de proyectos "privativos" que emplean a la "gente del linux"

Estoy por a punto contraer esquizofrenia aguda si no resuelvo el siguiente:

Estoy trabajando en una suite de proyecto$$$ de $oftware privativo$$$ (no hay problema en eso, el mundo es dinero) que esta empleando , como fuerza de trabajo tecnica principal, mucha "gente del linux" (me incluyo entre ellos) , seguidores de Richard Stallman (el tipo es un grosso) y sus enseñanzas filosoficas.
Exitosamente ambas partes ( la parte $privativa$, y la parte GNUsera ) han logrado dejar totalmente de lado sus prejuicios ideologicos para convivir en armonia en un proyecto que progreso (y progresa) bastante, como dos equipos remando en la misma direccion, al unisono, pero hasta cierto limite.
El limite surge cuando, se vislumbra una incompatibilidad de conceptos cuyas raices son esos profundos mandatos y estructuras ideologicas, conceptos de los que no se habla, pero se ven plasmado en los hechos.
El principal ejemplo de esto, es la aplicacion del concepto del "producto de software privativo", con la "propiedad intelectual" ( de lo cual estoy en contra y a favor de eso (mas en contra ( pero no al punto de rechazar el proyecto ) ) ), lo cual genera un obvio y comprensible requerimiento por parte del cliente de un producto autonomo ( que no requiera administracion, solo talvez mantenimiento ) y que por lo tanto tenga una gran plusvalia. No estoy en contra de eso, mas bien quiero lograrlo, pero la parte GNUsera no comprende, a nivel subconsciente, lo que significa el "producto de software privativo y que no necesite administracion", por lo tanto, sin darse cuenta, estan rechazando el desarrollo de soft en torno en la funcionalidad con parches (como reiniciar los servicios automaticamente ante un problema) y estan privilegiando el desarrollo de herramientas de monitoreo y administracion del servicio (cuando segun la otra parte, el servicio deberia administrarse solo ) y tambien estan dando prioridad al analisis detallado de bugs o problemas para darle solucion definitiva (como todo buen desarrollador de software libre) , pero siendo que esto no es para este contexto.
En este punto, si bien no tenemos a los dos equipos remando para sentidos opuestos y el barco girando sobre si mismo, no estan remando exactamente para la misma direccion, lo cual causa trayectorias circulares (de circulos bastante grandes), pero circulares al fin.
No se puede definir con certeza cual es la direccion correcta, el planteo de un "servicio que no necesite administracion" es bastante cuestionable, pero al mismo tiempo dejar que un servicio dependa en exceso de sus desarrolladores tambien es cuestionable, al igual que pretender que un producto privativo de poco personal este a la altura de soluciones libres o de grandes empresas. Hasta ahora solo describi el problema y no la solucion, pero es probable que si no se resuelve este problema, el proyecto no supere ese limite y yo termine en un loquero hablando con visiones :(

Comentarios acerca de posibles soluciones son bienvenidos

Highlighting a los post

Gracias a los instructivos de un buen post de este blog cuya direccion me paso Caco_Patane (pasense por su blog), pude configurar el highlighthing de codigo para los posts, ahora si que da gusto publicar post con codigo, vean el "hola mundo" del highlighting:


def holamundo
print "hola mundo!!!\n"
end

# los parentesis son un guiño
# para los que programan en C ;)
# son opcionales :D
holamundo()



Tambien el mitico factorial en ruby:


def factorial(n)
if n == 0
1
else
n*factorial(n-1)
end
end

jueves, 4 de diciembre de 2008

Cubos rubiks siameses, para no creer

Pasen y vean este fenomeno, cruel error de la naturaleza ( bastante creativo ) al parecer el cubovulo fue inseminado con dos juegos de stickers en lugar de uno, pero no llego a dividirse por completo como para generar cubos gemelos, y el resultado fue esta anomalia:



Un video de una resolucion bastante rapida del cubo:



Tambien un video con los tips de como resolverlo:

Robert, fijate la botella del agua

¿Fue a caso mi culpa ??, ¿ la mala suerte ?, ¿ sera el destino acaso, si tal cosa existe ?, ¿ o talvez sera la ineludible voluntad de los Dioses ?, mis preguntas comienzan a partir de una conjura de hechos que me ubicaron en el poder y la responsabilidad de ser el guardian universal de la botella atada con un cordon de zapatillas. Pero mejor explico (con narrativa anacronica)
Cuenta la historia de una vieja que se queja del agua que cae desde el aire acondicionado de nuestra oficina (el aire imprescindible en estas epocas de clima infernal/invernal (el mundo se volvio loco)), la onda es que se quejo , se quejo hasta que no se como terminamos instalando un complejo sistema de tubulacion que redirige la salida estandar del aire acondicionado a la entrada estandar de la botella.
Una vez, en una epoca , mas o menos al principio del 2008, en la empresa donde trabajo, deciden realzar una instalacion masiva en todas sus sucursales e instalaciones locales, sin percaterse de la anomalia q se avecinaba.
En un futuro post-apocaliptico, todos en la empresa mueren en un misterioso incendio
Todo esto lo termino escribiendo en un blog, mientras alguien intenta apagarme la maquina para evitar que la verdad sea rebelada
Antes de todo eso mande un curriculum para entrar a la empresa.
Despues de leer toda esa historia en el blog, empiezo a darme cuenta de mi ignorancia acerca de los limites entre la casualidad y la causalidad respecto de porque mi nuevo puesto de trabajo se encuentra convenientemente a 30 centimetros de la famosa botella, y a raiz de entonces, a cada rato me dicen "Robert, fijate la botella de agua" y de ahi me insipiro a inscribir ese articulo del blog

FIN???

Un blog agrego una referencia al mio

Es el blog de Diego Gomez, un compañero de laburo, les recomiendo este blog, es bastante completo y tiene todo lo bueno (solo le falta mas fedora y mas ruby, pero exceptuando eso es buenisimo)

Ahi tienen el blog
http://blog.dgomez.com.ar/

Y aca tienen el articulo que referencia a este blog, cerrando de esa manera una referencia ciclica, un circulo infinito referencial:

http://blog.dgomez.com.ar/node/46

Como me gusta escribir posts en este blog

Me gusta escribir post en un blog, sobre posts auto-referenciales como este, hoy empece un blog por presion, y al final estan presionando para que lo deje ¿?

Carencia de syntax highlighthing

Dirigido a los millones de seguidores del recien instaurado blog, les ofrezco mis mas sinceras disculpas por haber suspendido los post que incluyen tips de programacion ruby o de otros lenguajes inferiores. Las razones de esta determinacion, es el desconcimiento por parte mia de como ofrecer codigo en el blog con syntax highlighting (y ademas automatico), que de no existir puede causar graves problemas oculares y mentales (cuando chico, en mis inicios, prograba sin highlighting). Es asi, que en favor de la salud ocular, mental, psicologica y espiritual de los lectores, decidi suspender el envio de post que tengan codigo fuente hasta que resualva definitivamente el tema del syntax highlighthing. Disculpen las molestias ocasionadas

No soy un servidor DNS

Cada dos minutos recibo una peticion de resolucion de ip por chat, diciendo :
"pasame la ip de tal servidor", o "dame la ip de tal otro", o "¿te acordas cual es la ip de ese servidor" ?, y yo les contesto con la ip en cuestion de segundos mirando mis tablas hostname => ip. Me tienen la swap llena, un dia de estos voy a redirigir sus dnss a sitios porno, a ver si se dan cuenta... ( si leen este post no dejen que se enteren... )

Comentarios del codigo del post anterior (sin el codigo incluido, para q los pongan ustedes hehehe)

# leo el filename del primer argumento
# leo la expresion en lenguaje ruby del segundo argumento
# si no hay filename finalizo
# leo blocksize del tercer argumento y si no vino le asigno el default de 1
# leo init del cuarto argumento y si no vino le asigno el default de 1
# leo fin del quinto argumento y si no vino le asigno el default de 10
# abro el archivo para recorrerlo, de a bloques
# ejecuto la expresion pasada como parametro, como codigo ruby !!!

Como programar un editor hexadecimal programable en 15 minutos y usando menos lineas que el titulo de este post

Herramientas necesarias:
* ruby
* ruby
* ruby
* ganas de programar

... les debo las instrucciones ...

Codigo terminado:


class App
def main( args )
filename = args[0]
expresion = args[1]

if filename == nil
return
end

blocksize = ( args[2] || 1 ).to_i
init = (args[3] || 0).to_i
fin = (args[4] || 10).to_i

File.open(filename, "rb+") do |file|

i = init
while ( i < fin )
file.pos = i

stream = file.read(blocksize)
origstream = stream.clone

eval(expresion)

if stream != origstream

file.pos = i
file.write(stream)
end

i=i+1
end
end
end
end

App.new.main(ARGV)

NilClassBlog.new

Creado nuevo blog "NilClass", solo porque unos compañeros de laburo lo pidieron ( y creo q tenian razon ) ...