lunes, 19 de julio de 2010

Introducción a Structure Synth ( I )

Nada, ya está la primera parte de esta introducción a Structure Synth, sin mas dilación...

Todos lo que se puede hacer en Structure Synth se basa en unos elementos básicos llamados reglas, las reglas básicas (llamadas primitivas) son:

  • Sphere (esfera)

  • Box (caja)


  • Grid (Rejilla)


  • Line (Línea)


 Lo único necesario para que se muestre una regla es poner su nombre en el archivo que se va a "leer", por ejemplo


Sphere

Mostraría una esfera.

Como no, este lenguaje permite comentarios multilínea, desde  /*   hasta */ y comentarios de una sola línea, poniendo // al principio del comentario, como cualquier comentario en C.

Por cierto, si estas viendo que las imágenes tienen el fondo en blanco, pero si lo haces tu no, es por que hay que añadir


set background white

Ya explicaré más tarde para que sirve, pero no afecta a la programación en si.

Transformaciones geométricas: Movimiento, Traslaciones

En este lenguaje siempre se parte del sistema de coordenadas, para mover una regla lo que hay que hacer es mover sus coordenadas a través de lo que se llaman transformaciones, estas se especifican entre '{'  '}' antes de una regla, para mover el sistema de coordenadas del eje X en 2 unidades haremos
{ x 2 } regla

Lo mismo para cualquier otro eje ('Y' o 'Z'). Así si queremos poner dos cajas separadas, haremos


Box
{ x 2 } Box

El resultado es este:


Hay que recordar que las transformaciones solo se aplican para esa regla en concreto, las nuevas reglas seguirán partiendo del sistema de coodenadas original.


Box
{ x 2 } Box
{ x 4 } Box



Esto se puede hacer pesado si se tiene que repetir muchas veces, así que se puede utilizar un bucle que lo haga, la sintaxis para hacerlo es:
<numero de veces> * { <lista de transformaciones> } <regla>

Por ejemplo, si queremos que se repita lo que hemos estado haciendo (poner cajas separadas), digamos... 10 veces, haremos:


10 * { x 2 } Box


Importante: Cada iteración del bucle parte del sistema de coordenadas de la anterior (la primera parte del original)



Por supuesto, también se pueden anidar para hacer cosas más complejas, por ejemplo:


10 * { x 2 } 10 * { y 2 } Box




Transformaciones geométricas: Rotaciones

Otro tipo de movimiento que se realiza a través de las transformaciones es el de rotación, pero como la posición inicial depende del sistema de coordenadas, lo que se hace es rotar este sistema, por ejemplo, para rotarlo sobre el eje Y ( se "moverán" los ejes 'X' y 'Z' ), especificaremos una transformación
ry <grados de rotación>
(rx o rz para los ejes 'X' y 'Z' respectivamente )

Entonces, para dibujar un circulo solo hay que poner una caja, girar el eje 'X' (rotando sobre uno de los otros dos), y avanzar sobre este eje, repitiendo esto hasta que se hayan completado los 360 grados, por ejemplo:


360 * { ry 1 x 1 } Box


Transformaciones geométricas: Cambios de tamaño

Además se puede cambiar el tamaño del sistema de coordenadas, hacerlo implica cambiar el tamaño de las figuras y la distancia que se recorrerá con los mismos valores, la transformacion es:
s <proporción del nuevo sistema de coordenadas> 

La proporcion original es 1, 2 el doble, 0.5 la mitad...
Si al ejemplo anterior se le añade esta transformación...


360 * { ry 1 x 1 s 0.995 } Box



Si se añaden más iteraciones la espiral continúa...


1080 * { ry 1 x 1 s 0.995 } Box




Transformaciones de color: Tono, saturación y brillo

Structure Synth usa un tipo de color llamado HSV (Tono, saturación y valor), en vez del RGB, esto divide los colores en 3 valores, tono, la saturación y el valor (o brillo).
Tono es el "color" que tiene: rojo, verde, azul... La saturación, que indica la cantidad de color (va de blanco a todo color). Y el valor (o el brillo), que indica la cantidad de luz (de blanco a negro).

El tono va de 0 a  360 y vuelta a empezar (361 es igual a 1), su transformación es
hue <tono> 

Para ver como funciona de una forma más grafica, volveré al ejemplo del circulo (por problemas con Structure Synth esta pasado por Sunflow) ...


360 * { ry 1 x 1 hue 1 } Box



 La saturación es una proporción (como el cambio de tamaño), la transformación es
 sat <saturación> 

Volviendo al caso de las cajas contiguas:


10 * { x 1 sat 0.8 } Box



El valor (o brillo) es también una proporción, de 1 (claro) a 0 (negro), la transformación es
b <brillo>

Siguiendo con el ejemplo de las cajas contiguas


10 * { x 1 b 0.8 } Box

 Transformaciones de color: Alfa y colores absolutos

El alfa (o alpha) es el grado de transparencia que tiene un objeto, es una proporción, de opaco a totalmente transparente, la transformación es
 a <transparencia>

Si seguimos con las cajas...


10 * { x 1 a 0.8 } Box



 Por último decir que Structure Synth permite usar colores absolutos con la transformación
  color <color>

Los colores pueden ser RGB (rojo: #FF0000, verde: #0000FF ...) y los colores predefinidos de SVG (red, lightred, blue, gray ...)

Parámetros y preprocesador

Structure Synth se basa en unos parámetros para definir el "límite" de lo que se renderizará (ahora puede que no parezca muy lógico, pero con recursividad lo será), estos parámetros se especifican con:

set maxdepth <limite>      // Número máximo de generaciónes (iteraciónes o recursividad) antes de acabar
set maxobjects <limite>      // Número máximo de objetos antes de acabar
set minsize <limite>      // Tamaño mínimo de los objetos que se mostrarán antes de acabar
set maxsize <limite>      // Tamaño máximo de los objetos que se mostrarán antes de acabar
set background <color>      // Color de fondo (en RGB o con las palabras clave de SVG)

El preprocesador sirve para definir constantes de la misma forma que se hace en C, no tiene ninguna dificultad...
#define nombre_de_la_constante constante



Mezclando un poco de todo...


1080 * { ry 1 x 1 hue 1 s 0.997 } Box




Eso es todo por ahora, con el próximo más y mejor: definir nuevas reglas, recursividad, fractales, aleatoriedad...

Hasta entonces

jueves, 15 de julio de 2010

Structure Synth y Sunflow, diseño en 3D

Hoy traigo un par de herramientas, de las que supe por un mail, son Structure Synth y Sunflow.

Structure Synth se encarga de la parte del diseño, con una peculiaridad, en vez de hacer las figuras a mano, se las "describe" a través de una gramatica... para entendernos, se programan, pero a diferencia de la mayoria de los lenguajes, no hay variables (hay parámetros, pero solo unos predefinidos) ni condiciones, todo está definido como un conjunto de figuras ("rules", reglas), que son algunas figuras básicas (cubos, esferas, lineas...). El truco suele estar en usar la recursividad de las reglas (que una misma regla se llame a si misma, lo que lo hace ideal para generar fractales) y , aunque menos, las repeticiones, como repetir muchos cubos para hacer una especie de aro.


Solo un comentario, si usas GNU/Linux, probablemente el paquete del repositorio falle, así como la compilación desde el código, a falta de otra solución mejor, se puede usar Wine con el paquete de Windows, que sorprendentemete va muy bien es usable aún emulado, supongo que porque no usa ninguna librería única de Windows (¿?)
Página web: http://structuresynth.sourceforge.net/
Descarga: http://structuresynth.sourceforge.net/download.php

Sunflow se encarga de la parte del renderizado, si exportamos las imágenes de Structure Synth, (F6) y se las pasamos a Sunflow, el resultado será mucho mejor que el propio de Structure Synth.

Este funciona perfectamente con GNU/Linux (está en java).
Página web: http://sunflow.sourceforge.net/
Descarga: http://sunflow.sourceforge.net/index.php?pg=down (o el sistema de paquetes de tu SO)


En los próximos post intentaré hacer un tutorial sobre Structure Synth (el uso básico de Sunflow, a partir de archivos ya generados, es fácil), ya que no hay ninguno por la red.

Sin más dilación algunas muestras de lo que se puede hacer con estos dos programas:

La primera es obra de Vishkey, responsable de que haya encontrado estos programas, es un triángulo fractal:



set maxobjects 1000000

R1

rule r1 maxdepth 5 > c2 { //El 5 hace referencia a la profundidad del fractal
   {s 0.5 hue 5}  R1
   {s 0.5 x 1 hue 5} R1
   {s 0.5 y 0.865  x 0.5 hue 5} R1
}

rule c2 {
  linea
  {rz 60 x 0.25 y 0.433} linea
  {rz -60 x -0.25 y 0.433} linea
}

rule linea {
 {s 1 0.1 0.1} box
}



Otro código del mismo autor (con este me tome la libertad de bajar el maxdepth a 50 porque sino, con Wine, el renderizado no era posible):


r2

rule r2 maxdepth 100 {
  4 * {rz 90 hue 4} r1
  { s 0.75 z 1 rz 30 a 39} r2
}

rule r1 maxdepth 100{
  box
  {s 0.9 y 0.3 rz 5} r1
}


Un ejemplo de la web, que también tiene su interes:


/*
Sample Torus.
*/

set maxdepth 100
r1

36 * { x -2 ry 10   } r1

rule r1 maxdepth 10 {
   2 * { y -1 } 3 * { rz 15 x 1 b 0.9 h -20 } r2
   { y 1 h 12 a 0.9 rx 36 } r1
}

rule r2 {
   { s 0.9 0.1 1.1 hue 10 } box // a comment
}

rule r2 w 2 {
   { hue 113 sat 19 a 23 s 0.1 0.9 1.1 } box
}


Y por último, un aporte propio:


/*

Trisquel Structure Synth figure.
*/

set maxdepth 75

{ color #195EB9 } base

rule spiral_base {
  { x 1 rz 6 ry 6 s 0.975 } spiral_base
  { s 1 } box
}

rule arm1 {
  { rx 140 } spiral_base
}

rule arm2 {
  { rx 60 ry 36 rz 120 } spiral_base
}

rule arm3 {
  { ry -60 rz 180 }  spiral_base
}

rule base {
    arm1
    arm2
    arm3
    { s 2} sphere
}


Hasta la próxima.

martes, 13 de julio de 2010

jGuess: Reconociendo tipos de archivos por los números mágicos

Actualización: Arreglado el problema del "ejecutable"... lo que tiene  no comprobar las cosas

Hoy traigo un pequeño experimento en Java, una especie de file con GUI

Si alguna vez habéis intentado ver (por ejemplo) lo que hay en la carpeta de caché de Firefox, todos los archivos están sin extensión, en estos casos se puede utilizar simplemenente el comando file, pero para quien no tenga una máquina *nix, o no quiera andar con el terminal, quizá quiera probar esto, no es ni de lejos tan potente como file, pero puede servir, además puede añadir las extensiones automáticamente.


O con archivos normales:

Para descargar: [jguess.zip] ( descomprimir y ejecutar el .JAR )
El código fuente: [jguess_src.zip]

Tiene algunas carencias (no soporta los que tienen números variables, como avi), pero para algo rápido sirve.
El que esté en inglés es por que gran parte del código de los números mágicos ya lo tenía escrito, en inglés, y por no cambiar todo... xD

ps: a ver si luego subo algo de un programa de arte en 3D que está simplemente genial, Stay tuned

[Referencias]
http://www.garykessler.net/library/file_sigs.html (algunas)
https://secure.wikimedia.org/wikipedia/en/wiki/Magic_number_%28programming%29
http://www.digitalpreservation.gov/formats/ (algunas)

sábado, 10 de julio de 2010

HTTPS en todos sitios

(Además de ser lo que es, este post está aquí por curiosidad, para saber cuanto tarda Blogger en publicar un post programado, por ejemplo, para las 23:59)

Hace tiempo que pensaba hablar de esto, pero me pareció demasiado offtopic, ahora... también.

Traduciendo lo que pone en su web:

HTTPS Everywhere es una extensión de Firefox producida en colaboración entre El proyecto Tor y la Electronic Frontier Foundation. Encripta tus comunicaciónes en varias webs "importantes".

Muchos páginas web ofrecen una encriptación limitada sobre HTTPS, pero se hace dificil de usar. Por ejemplo, ellos pueden usar por defecto el HTTP sin encriptar o llenar páginas cifradas con enlaces que vuelven al sitio sin encriptar.

La extensión HTTPS Everywhere arregla esos problemas reescribiendo todas las peticiones a esas páginas a HTTPS. Los usuarios de Firefox la pueden conseguir haciendo click aqui:

Para saber con que páginas funciona, visita:
https://www.eff.org/https-everywhere

Hace bastante tiempo que anda por ahí (hace quizá un mes o más que se hablo de esto en la lista de correo de TOR)

Hasta otra.

viernes, 9 de julio de 2010

Comprobar links de megaupload desde bash

Gracias a Mungu ayer descubrí que bash puede abrir conexiones tcp/ip directamente, sin depender de netcat ni telnet, así que ahí va una pequeña prueba/experimento...

Dice "OK" y sale con 0 si el link a megaupload es correcto, o dice "Invalid link" y sale con 1 si es incorrecto.

Actualizado: ahora funciona también con links sin "www"


#!/usr/bin/env bash

if [ "$1" = "" ]; then
    echo "No has especificado una dirección"
    exit 1
else
    path="/?"`echo $1|cut -d? -f2`
fi

# Request webpage
exec 3<>/dev/tcp/www.megaupload.com/80
echo -en "GET $path HTTP/1.1\r\n" >&3
echo -en "HOST: www.megaupload.com\r\n" >&3
echo -en "Connection: close\r\n\r\n" >&3
cat <&3|grep "Invalid link" >> /dev/null

result=$?
if [ $result -ne 0 ];then
    echo "OK"
    result=0
else
    echo "Invalid link"
    result=1
fi
exit $result


[Referencias]
Bash socket programming with /dev/tcp

jueves, 8 de julio de 2010

Listas de palabras de Wikitionary

Como experimento y para probar la nueva versión de Pywc, nació (más bien se escribió) un script que usa Wikitionary (el diccionario de la Wikipedia) para extraer listas de palabras.

La sintaxis es:


./wikiwords.py [-help] [-min <tamaño>] [-max <tamaño>] [-lang <lenguaje>] [-numpags <número>] [-incial <palabra>] [-nullwd <lista>]
-help: muestra esto
-min: las palabras de salida serán como mínimo de <tamaño> letras
-max: las palabras de salida serán como máximo de <tamaño> letras
-lang: se usara el wiki en <lenguaje>
-numpags: se leeran <número> páginas
-inicial: la palabra inicial será <palabra>
-nullwd: la lista de palabras "inútiles" (artículos) está en <lista> o no existe (off)


La lista de palabras "inútiles" de ejemplo es:


cual
cuales
de
el
la
los
las
o
y
que
se
en
un
una


El script se puede descargar aquí [wikiwords.zip] (con la lista de palabras) y con Pywc [wikiwords_03.zip].
Y el código coloreado con pygments...


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Escrito por kenkeiras [CodigoParaLlevar.blogspot.com]

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by

    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

import pywc, string, sys

argc = len(sys.argv)

def show_help():

    print "./wikiwords.py [-help] [-min <tamaño>] [-max <tamaño>] [-lang <lenguaje>] [-numpags <número>] [-incial <palabra>] [-nullwd <lista>]"

    print "-help: muestra esto"
    print "-min: las palabras de salida serán como mínimo de <tamaño> letras"
    print "-max: las palabras de salida serán como máximo de <tamaño> letras"

    print "-lang: se usara el wiki en <lenguaje>"
    print "-numpags: se leeran <número> páginas"
    print "-inicial: la palabra inicial será <palabra>"

    print "-nullwd: la lista de palabras \"inútiles\" (artículos) está en <lista> o no existe (off)"

# Caracteres que componen las palabras
# Characters that compose words

global textchars
textchars = u"abcdefghijklmnñopqrstuvwxyzABCDEEFGHIJKLMNÑOPQRSTUVWXYZáéíóúüÁÉÍÓÚÜ"

# Si es una simple palabra
# If is a plain word
def isClean(s):

    global textchars
    try:
        for c in unicode(s):

            if (not c in textchars):
                return False

    except Exception as ex:
        return False
    return True

# Valores por defecto
# By default values
minchars = 0 # Caracteres mínimos
maxchars = 100 # Caracteres máximos

numpags = 100 # Páginas que se recorrerán
inicial="meta" # Palabra inicial
lang = "es" # Lenguaje

nullwords = "nullwd" # Useless word list



# Reading command line options
# Leyendo las opciónes de linea de comandos
i = 1

while ( i < argc ):
    if ( sys.argv[i] == "-min" ): # Opción: -min

        i += 1
        minchars = int (sys.argv[i])

    elif ( sys.argv[i] == "-max" ):# Opción: -max

        i += 1
        maxchars = int (sys.argv[i])

    elif ( sys.argv[i] == "-lang" ):# Opción: -lang

        i += 1
        lang = sys.argv[i]

    elif ( sys.argv[i] == "-numpags" ):# Opción: -numpags

        i += 1
        numpags = int (sys.argv[i])

    elif ( sys.argv[i] == "-inicial" ):# Opción: -inicial

        i += 1
        inicial = sys.argv[i]

    elif ( sys.argv[i] == "-nullwd" ):# Opción: -nullwd

        i += 1
        nullwords = sys.argv[i]

    elif ( sys.argv[i] == "-help" ):# Opción: -help

        show_help()
        sys.exit(0)

    i += 1

# Caracteres que separan palabras
# Characters that split words
splitchars = ",.-/+|:!?\"'\\&\n"

new = ["http://"+lang+".wiktionary.org/wiki/"+inicial] # próximas Url's

wordlist = ['wikitionary'] # Lista de palabras que ya salieron

# Add null characters to the list
# Se añaden los caracteres nulos a la lista
if (nullwords.lower() != "off"):

    try:
        f = open(nullwords,"r")
        line = f.readline()

        while ( len (line) > 0 ):
            line = line.replace("\n","").replace("\r","").strip()

            if (len (line) > 0) and (not line in wordlist):

                wordlist.append(line)
            line = f.readline()

        f.close()
    except Exception as ex:

        print >> sys.stderr, "Error al leer archivo de palabras nulas:",ex

crawler = pywc.crawler() # Se inicia el crawler

# Comienza la acción...

while ( len(new) > 0 ) and (numpags > 0):

    site = crawler.crawlsite( new.pop(0) ) # Se lee la página

    inPost = False
    numpags -= 1

    for el in site.element_list: # Para todos los elementos de una página

        if (el.tag_type == "div"):
            try:

                if ("id" in el.property) and \
                    ( el.property['id'] == "bodyContent" ): # Si es el inicio

                    inPost = True                            # del artículo...

                elif ( el.property['class'] == "printfooter" ): # Si es el

                    break                                     # final...
            except:
                pass

        if (inPost) and (not el.tag): # Si es parte del artículo

            el.text = el.text.lower()
            tmp = el.text.strip()

            for schar in splitchars: # Se separan las palabras
                tmp = tmp.split(schar)

                tmp = string.join(tmp," ")

            for word in tmp.split(" "): # Se comprueba cada palabra

                                        # por separado

                # Se comprueba que sean palabras normales, que no excedan
                # los límites y que no estén repetidas
                if (isClean(word)):
                    lonx = len(word)

                    if ( lonx > 0 ) and ( lonx >= minchars ) and \
                     ( lonx <= maxchars ):

                        if (not word in wordlist):
                            wordlist.append(word)

                            print word
                            new.append("http://"+lang+".wikipedia.org/wiki/"+\
                                word)

Pywc 0.3 (antes PyCrawler)

El cambio de nombre viene porque con una búsqueda en Google por "PyCrawler" se encuentran choporrocientos scripts, asi que para evitar confusiones... Python Web Client -> Pywc

Por lo demás, los añadidos son pocos, un poco de DOM con las funciones website.getElementById(element_id), website.getElementsByName(name) y website.getElementsByTagName(tag), y un nuevo atributo de los website, website.title, todo esto se usaría igual que desde JavaScript (que es la idea).

Además hay algunas correcciones, como los elementos que no sean tags (element.tag == False) tienen un atributo element.text que guarda (obviamente) el propio texto. Si se llama a crawlsite con el segundo parámetro (save_raw) a True, se guarda una copia del site original en el atributo web.raw. Por último, se arregló un problema con las URL.

Aquí el ZIP con esto: [pywc_03.zip]
El crawler actualizado: [fastcrawler_03.py]
Y el descargador de lista de proxies actualizado: [proxylist_03.py]

lunes, 5 de julio de 2010

Hablando por el terminal

Hoy traigo algo medio OffTopic, para pasar el rato.

Un intérprete de comandos ya permite pasarse horas programando cosas más o menos útiles, pero si además le añadimos un sintetizador de voz, las posibilidades solo las limita la imaginación.

eSpeak es un programa (disponible a través del paquete correspondiente) que permite usar un sintetizador de voz por línea de comandos (aunque tambien tiene una gui), la entrada por defecto se hace por stdin, así que utilizando tuberías (pipes) se pueden hacer cosas bastante curiosas, el parámetro más a tener en cuenta es la voz (que regulará la pronunciación), por defecto es el inglés, pero con -ves se puede configurar para castellano, la sintaxis, es -v[código del idioma]

Algunos ejemplos de su uso pueden ser



fortune | espeak -ves


para que lea una frase aleatoria

o


i=1
while [ $i -le 10 ]
    do
    j=1
    while [ $j -le 10 ]
        do
        r=$(( $i * $j))
        echo "$i por $j es = a $r"
        j=$(($j + 1))
    done
    i=$(($i + 1))
done|espeak -ves


o en una línea


i=1;while [ $i -le 10 ]; do j=1; while [ $j -le 10 ]; do r=$(( $i * $j)); echo "$i por $j es = a $r"; j=$(($j + 1)); done; i=$(($i + 1)); done|espeak -ves


para que diga la tabla del 1 al 10

El resto es cuestión de imaginación, combinado con un poco de scripting puede servir para que avise cuando la temperatura del PC sube demasiado, cuando llegue una hora preconfigurada (típica alarma)  o cuando alguien está hablando con nosotros por el IRC... lo difícil es encontrar algo para lo que sea realmente necesario :)

Hasta otra.

[Referencias]
http://espeak.sourceforge.net/

domingo, 4 de julio de 2010

Números pseudo-aleatorios con Pascal

La generación de números pseudo-aleatorios es una característica que la mayoría de lenguajes de programación implementa por defecto, pero Pascal estándar extendido es una excepción (el FreePascal no, ojo).

Esta historia viene porque hace tiempo necesitaba generar estos números para un programa en Pascal, y al no encontrar nada (aunque bueno... tampoco busqué mucho :P ) programé  algo. No es gran cosa, si se conocen los dos números anteriores y el momento en el que se inició el generador (con una precisión de microsegundos) se puede intentar descubrir cual será el siguiente, pero sirve para algo básico.

Para usarlo solo hay que importarlo y llamar a la función random usando el número "tope" como parámetro, por ejemplo, para generar un número del 0 al 100 (ambos incluidos):


aleatorio := random(100);



El código es este, se basa en el cifrado ARC4 (a.k.a RC4), y para descargar [random.pas]


module mod_random;

{
Copyright (C) Kenkeiras 2010

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by

    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.


Modulo de numeros aleatorios

    Contiene las funciones para generar numeros aleatorios

    - random

}


export mod_random=(random);

function random(top:integer):integer;
type
    tbyte=0..255;

var
    S: array [0..255] of tbyte;
    i,j: integer;

end;

{ procedure swap (var c1:tbyte;var c2:tbyte);
    Intercambia dos bytes
}
procedure swap (var a,b:tbyte);

    var
     temp:tbyte;
    begin
     temp:=b;
     b:=a;
     a:=temp;
    end;

{ procedure random_seed;

    Inicia la caja para generar los numeros pseudo-aleatorios

}
procedure random_seed;
    var
        t:timeStamp;
        str:string(255);
        n:integer;

    begin
        getTimeStamp(t);
        str:=time(t);

        for n:=0 to 255 do
            S[n]:=n;

        j:=0;
        for n:=0 to 255 do begin
            j:=(j+S[n]+ord(str[(n mod length(str))+1]))mod 256;
            swap(S[n],S[j]);
        end;

        i:=0;
        j:=0;
end;

{ function random_byte:tbyte;

    Precondicion: La caja esta iniciada
    Devuelve un byte pseudo-aleatorio

}
function random_byte:tbyte;
    begin
        i:=(i+1)mod 256;
        j:=(j+S[i])mod 256;

        swap(S[i],S[j]);
        random_byte:= S[(S[i]+S[j])mod 256];
    end;

{ function random(top:integer):integer;

    Precondicion: La caja esta iniciada
    Devuelve un numero (integer) pseudo-aleatorio con un valor maximo de 'top'

}

function random;
    var
        n,k:integer value 0;

    begin
        for n:=((top div 256)+1) downto 0 do
            k:=k+random_byte;

        random:=(k mod top)+1;
    end;

to begin do
    { Al iniciar el programa inicia la caja para poder generar numeros aleatorios }
    random_seed;

end.



Y eso es todo... hasta otra.

sábado, 3 de julio de 2010

ASCII Art con Python [Actualizada]

[Actualizado, añadidos más caracteres y arreglado el problema con el unicode]

Hoy traigo algo curioso, un script que hace ASCII Art a partir de una frase cualquiera.

El script se puede descargar aquí [asciichars.py]

Los parámetros son ./asciichars.py [ -s <espaciado> ] [ <frase> ]

El espaciado es (obviamente) el espacio entre los caracteres, por defecto 8. Y la frase, lo que aparecera en el ASCII Art (si no se especifica, se pedirá durante la ejecución).

La verdad, no tengo muy claro como explicarlo :D, así que para muestra un botón
./asciichars.py -s 10 "#28"


Los caracteres que hay son:



0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N Ñ O P Q R S T U V W X Y Z [Espacio] ! # | + - = . ] [



El juego completo de caracteres...

Hasta otra!