Bienvenidos a un lugar donde la programación, los vídeos, las divagaciones y las subnormalidad se combinan para demostrar que el caos puede ser bello.
Serabe Reloaded
Conecto ergo sum. Non conecto ergo urgueo.
"Que esté paranoico no quiere decir que no me estén persiguiendo."
Leído por ahí.
RMagick4J 0.3.6
I am glad to announce a new version of rmagick4j.
RMagick4J aims to implement the ImageMagick funcionality and the C
portions of RMagick for make it works in JRuby.
Current stable version: 0.3.6
Project URL: http://code.google.com/p/rmagick4j/
Installation: gem install rmagick4j
Google Summer of Code project should be thanked for making this new
release possible.
In release 0.3.6 you can find the next improvements:
- More Draw primitives (clip-path [creatin a clip-path and using a
clip-path], fill-rule, rotate, scale [reimplemented], skewX, slewY,
stroke-linecap, stroke-linejoin, stroke-miterlimit, translate). - Solve a bug with transparent stroke and line primitive.
- Added the following Draw instance methods:
- annotate
- get_multiline_type_metrics
- Solved a bug that caused the background become black while resizing
images with alpha channel.
Please try out your applications with rmagick4j and help us provide
feedback. It is our goal to make a fully-compatible implementation of
RMagick4j in JRuby.
Sustituyendo a las animadoras con Ruby en Mac.
El título del post puede sonar raro, pero lo que voy a mostrar hoy es cómo conseguir tu propia animadora en Mac con Ruby. Lo que haremos será hacer que nuestro ordenador, con una orden como:
ruby cheerleader.rb Serabe
Nos muestre por pantalla:
Dame una S
Dame una E
Dame una R
Dame una A
Dame una B
Dame una E
SERABE!!!
Además, utilizando el comando say de Mac, nos lo dirá (si queréis que lo grite, subid el volumen al máximo).
Empecemos con el código:
-
string = ARGV.join(' ')
Aquí simplemente recogemos los parámetros pasados por consola y los concatenamos con un espacio entre medias. Ahora la parte interesante:
-
string.each_byte do |b|
-
if /[a-zA-Z]/ =~ b.chr
-
shout = 'Dame una '+b.chr.upcase
-
puts shout
-
`say #{shout}`
-
end
-
end
Para cada letra, una vez comprobado que es una letra y no un espacio, construimos un grito ('Dame una S'), lo imprimimos por pantalla y hacemos que el comando say lo diga.
Finalmente, con un
-
puts string.upcase + '!!!'
-
-
`say #{string}`
Imprimimos la última frase.
Ya habéis visto cómo crearos vuestra propia cheerleader. En próximos episodios veremos cómo añadirle autoregeneración como Claire.
RMagick: Dibujar con patrones
Una interesante cualidad de la clase Draw de RMagick es la posibilidad de definir patrones a través del método pattern.
En primer lugar, lo básico:
-
require 'rubygems'
-
require 'RMagick'
-
-
include Magick
Ahora definamos el patrón. Para ello, necesitamos cinco parámetros, el nombre, dos números que recomiendo ponerlos a cero (después de unas cuantas pruebas, no he notado diferencias notables) y después las dimensiones del patrón.
-
draw = Draw.new
-
-
draw.pattern('circles', 0, 0, 10, 10) do
-
draw.stroke 'none'
-
draw.fill 'red'
-
draw.rectangle 0, 0, 10, 10
-
draw.stroke 'LightGreen'
-
draw.fill 'blue'
-
draw.circle 5, 5, 5, 0
-
end
Ya, por último, dibujamos un cuadrado y lo plasmamos en una imagen de 300x300.
-
draw.stroke 'circles'
-
draw.stroke_width 25
-
-
draw.fill 'none'
-
-
draw.polygon 150,0, 300,150, 150,300, 0,150
-
-
img = Image.new 300, 300
-
-
draw.draw img
-
-
img.write 'pattern.jpg'
Obteniéndose el siguiente resultado:
New RMagick4J release.
RMagick aims to implement the ImageMagick funcionality and the C portions of RMagick for make it works in JRuby.
Current stable version: 0.3.5
Project URL: http://code.google.com/p/rmagick4j/
Installation: gem install rmagick4j
Google Summer of Code project should be thanked for making this new release possible.
In release 0.3.5 the following improvements have been made:
- Implemented Draw primitives (affice, arc, pattern, path).
- Improved Image and ImageList:
- Implemented more of Pixel (from_HSL, to_HSL, <=>, fcmp, intensity).
- Implemented the fill classes.
- Added a side-by-side (MRI vs JRuby) image testing tool named Bullseye.
- Added 680 color names. It can search, but not retrieve the name correctly capitalized.
- Changed gem name from RMagick4J to rmagick4j.
This version should allow Gruff Graphs and Ruports to largely work without issues. Please try out your applications with rmagick4j and help us provide feedback. It is our goal to make a fully-compatible implementation of RMagick4j in JRuby.
Ay, Serabe, que no haces nada ni tan siquiera regular.
Hoy me he tirado unas cuatro horas para encontrar un bug, uno de estos puñeteros bichos que te atrapan y te dejan cosas como estas:

Para que os hagáis una idea, tenía que ser esto:

Como se puede apreciar, son sensiblemente diferentes. Así que cuatro horas de mi vida han transformado lo primero, en lo segundo.
El problema venía en que, tal y como Tom (mi mentor del GSoC) propuso, se ha cambiado la clase PixelPacket de forma que ahora trabaja con enteros. El problema, mejor no os lo cuento que es más aburrido que lo anterior.
En fin, que hoy me voy a la cama con un ego más grande que el de Enrique Dans.
Sweating blood
Si alguno está investigando sobre las Stories de RSpec, y no consigue hacerlas funcionar, un
-
require 'spec/story'
debería solucionarlo todo...
Joder lo que hace mi inutilidad y mi falta de documentación.
Problema 2
Enunciado:
Suma todos los números pares de la sucesión de Fibonacci menores que un cuatro millón.
Primera solución:
La primera solución es muy simple. Hay un método que devuelve un array con todos los números de la sucesión de Fibonacci menores que un máximo max tomando como inicio un array de dos elementos arr.
-
def fib1(max,arr=[1,1])
-
while(arr.last <max) do
-
arr <<(arr.last+arr[arr.size-2])
-
end
-
arr.pop
-
arr
-
end
Después simplemente se eliminan los impares y se suman los que quedan.
-
def euler2a(max, ini=[1,1])
-
fib1(max,ini).delete_if{|x| x%2 == 1}.inject{|memo,obj| memo+obj}
-
end
-
-
puts euler2a(4e6)
Segunda solución:
Esta solución es un poco mejor. Se va a hacer un nuevo método que calcule todos los números de la sucesión de Fibonacci menores que un máximo max pero que sólo almacene aquellos que pasen una condición que se le pasa como bloque:
-
def fib2(max,a=1,b=1)
-
arr = []
-
arr <<a if yield(a)
-
while(b<max) do
-
arr <<b if yield(b)
-
a,b=b,a+b
-
end
-
arr
-
end
Después sólo hace falta pasar el filtro adecuado, y sumar los resultados:
-
def euler2b(max,a=1,b=1)
-
fib2(max,a,b){|x| x%2==0}.inject{|memo,obj| memo+obj}
-
end
-
-
puts euler2b(4e6)
Tercera solución:
Esta tercera solución es una modificación directa de la segunda. En vez de almacenar los datos, se suman directamente.
-
def fib3(max,a=1,b=1)
-
res = 0
-
res += a if yield(a)
-
while(b<max) do
-
res += b if yield(b)
-
a,b=b,a+b
-
end
-
res
-
end
-
-
def euler2c(max,a=1,b=1)
-
fib3(max,a,b){|x| x%2==0}
-
end
-
-
puts euler2c(4e6)
Y eso es todo.
Actualización: Hay diferencias entre la página de PyEuler y la del Proyecto Euler. El problema ha sido actualizado para corresponderse con esta última.
Gráficos de radar o de araña con Gruff
Gruff es una librería de Ruby para realizar gráficos. Es muy simple de usar, pero para ello, primero se ha de instalar. Nada más fácil:
sudo gem install gruff
Una vez instalado, se puede usar uno de los múltiples tutoriales que hay por Internet. Yo, por mi lado, me he decidido a hacer uno de un gráfico aún experimental: el gráfico de radar o de araña.
En primer lugar, importamos las librerías necesarias:
-
require 'rubygems'
-
require "gruff"
Para seguir, creamos el objeto necesario y le damos título:
-
g = Gruff::Spider.new 10
-
g.title = "Calificaciones"
Ahora, añadimos los datos. El primer parámetro es el nombre que va a aparecer al lado del dato en cuestión. El segundo es un array de datos numéricos, en el caso que nos ocupa, es un simple número. Hay un tercer parámetro opcional: el color en hexadecimal.
-
g.data "Matemáticas", 8.5
-
g.data "Historia", 6.7
-
g.data "Lengua y Literatura", 5.3
-
g.data "Eduación Física", 4.8
-
g.data "Física y Química", 8.9
-
g.data "Religión", 10
Ahora ya sólo queda guardar la imagen, lo cual es muy fácil. Simplemente:
-
g.write('marks.png')
He aquí el resultado (algunas letras se tapan con las líneas puesto que aún está en fase experimental):
En mi máquina, la media de ejecutarlo 100 veces es 0.32048496 segundos, el máximo es 0.40913s y el mínimo, 0.314553s.
Y eso es to, eso es to, eso es todo amigos.
Problema 1
Empiezo aquí una serie de artículos de periodicidad variable que lo único que pretende es ser algo similar (de una manera muy amplia) a PyEuler. La lista completa de problemas está en el Proyecto Euler y, como no podía ser de otra manera, empiezo por el primero.
Enunciado:
Halla la suma de todos los números menores que 1000 y múltiplos de 3 o de 5.
Solución 1:
-
def euler1a(e, numbers)
-
(1..e).select{|x| numbers.any?{|y| (x%y == 0)}}.inject{|memo,o| memo+=o}
-
end
-
-
puts euler1a(1000,[3,5])
La explicación es simple. Tenemos un rango desde 1 hasta el límite, filtramos los que son múltiplos de algún elemento del array y después se suman.
Solución 2:
-
def euler1b(e,numbers)
-
(1..e).inject(0){|memo,o| (numbers.any?{|x| (o%x)==0}) ? memo+o : memo }
-
end
-
-
puts euler1b(1000,[3,5])
Éste es similar al anterior, sólo que se suma según se recorre el rango.
Solución 3:
Para este necesitamos antes un par de funciones. La primera, halla el máximo común divisor de dos números. Para ello, básicamente usa el algoritmo de Euclides.
-
def mcd(n1,n2)
-
if n1 <n2
-
mcd(n2,n1)
-
elsif (n1%n2) == 0
-
n2
-
else
-
mcd(n2,n1%n2)
-
end
-
end
Por otra parte, está la función que calcula el mínimo común múltiplo. Para ello usa su relación con el m.c.d..
-
def mcm(n1,n2)
-
n1*n2/mcd(n1,n2)
-
end
Con esto, ya podemos pasar a la tercera solución, que es diferente de las otras dos en que sólo sirve si utilizamos dos números como filtro.
-
def euler1c(limit, n1, n2)
-
(n1*((limit/n1)*((limit/n1)+1)/2)+n2*((limit/n2)*((limit/n2)+1)/2)-mcm(n1,n2)*((limit/mcm(n1,n2))*((limit/mcm(n1,n2))+1)/2))
-
end
-
-
puts euler1c(1000,3,5)
La explicación es un poco más complicada, pues implica teoría básica de conjuntos y la conocida fórmula de la suma de 1 a n.
Ahora es vuestro turno. ¿Cómo se os ocurre hacerlo?
Resolución: ejercicio y números confuso.
Hace tiempo que conozco el blog Programancia101, un blog con "retos" de programación. Hace tiempo sacaron éste, como algún otro lo leí, pero pasó que estaba en una época de mi vida en la que me apetecía mucho programar, y me decidí a resolverlo. El problema, básicamente, consiste en, dadas una reglas de "confusión" y un número, averiguar las posibles confusiones, tanto al derecho, como al revés. Sé que parece lioso, por eso os remito al enunciado , otra vez. Sería interesante que fueseis viendo el código fuente al mismo tiempo y al menos haberlo pensado un par de veces (si no, no hay diversión).
Nota previa.
Aunque hable de número, internamente es más cómodo, en este caso, trabajar con cadenas. Por lo tanto, aunque diga número, el tipo es String.
Paso 1: Almacenamiento de las "confusiones".
Para almacenar las confusiones opté por un hash que contenía otros dos: straight (para las confusiones al derecho) y reverse (para las confusiones si están dados la vuelta). En cada uno de ellos, a cada número se le asigna un array con las posibles confusiones (dadas en el enunciado). Es obvio, que en el hash straight deberán estar también contenidos los propios números. El hash se define desde la línea 22 a la 48.
Paso 2: Redefiniendo la clase String para nuestros oscuros propósitos.
En la clase String, se necesitan dos nuevos métodos: little y reversible?. El primero devuelve toda la cadena excepto el primer carácter, para qué, en el siguiente paso. El método reversible? comprueba si todos los números son reversibles, es decir, el array de confusiones del hash CONFUSIONS[:reverse][numero.to_sym] es no vacío. Esto se hace de la línea 4 a la 19.
Paso 3: La idea.
La idea de la resolución es muy sencilla. Dado un número, las posibles confusiones se corresponden con las confusiones del mismo número sin la unidad de mayor orden (por ejemplo, si el número es el 12345, el número sin la unidad de mayor orden es el 2345) combinadas con las posibles confusiones del primer número (en el caso anterior, el 1). Por lo tanto, aquí entra la recursión, y de ahí la necesidad del método little de la clase String (recordemos que los números, en este caso, los guardamos como cadenas). El método en cuestión recibe dos parámetros, el número y el hash de confusiones, que por defecto es CONFUSIONS[:straight]. Por supuesto, necesitamos de otra función. En ella, lo que hacemos es obtener el array de confusiones al derecho y mezclarlo con el de las confusiones al revés, si las hubiera. Una vez hecho esto, se eliminan duplicados y se ordena. Estas funciones se encuentran definidas desde la línea 53 a la 75.
Paso 4: Los retoques.
Por último, añadir una comprobación de los parámetros (se ha de recibir un único parámetro que sea un número). Esto se realiza de la línea 78 a la 82. Posteriormente se llama a la función (línea 83) y se muestran los resultados (línea 85).
"Operadora, dígame el número del 911."
Homer Simpson
