El blog de Juan Palómez

23 diciembre 2011

Wappo solver

Archivado en: Uncategorized — Etiquetas: , , , , — thisisoneball @ 17:22

This is a Lisp program that solves any level of the game Wappo. It’s a Java game that came with Siemens mobile phones.

You have to code the layout of the level you want to solve. At the end of the program you can see the example for the first three levels of the game. You have to enter the starting coordinates of Wappo, one or more Yumchaks (the enemies), the pits, the walls (in this case you enter the coordinates of the two tiles that surround the wall), and the exit.

It will print the sequence of moves you have to make. Works at least with CLISP for Windows

 


;; (board wappo (yumchaks) (pits) (walls))
;; (setq state (cons (make-list 6 :initial-element (make-list 6)) '((3 4) ((5 4)) ((1 4)) ((1 3 1 4) (3 4 3 5) (5 4 5 5) (5 4 4 4) (5 0 4 0)))))

(defun allowed (state from to)
(let (wall pit)
  (setq from (subseq from 0 2))
  (if
    (or
      (> (first to) 5)
      (< (first to) 0)
      (> (second to) 5)
      (< (second to) 0)
    )
    nil
    (if
      (dolist (wall (fourth state) t)
        (if (or (equal (append from to) wall) (equal (append to from) wall))
            (return nil)))
      (if (equal from (first state))
        (dolist (pit (third state) t)
	  (if (equal to pit)
	      (return nil)))
	t)
    )
  )
)
)

(defun randomize-list (l)
  (if (not (null l))
    (let ((element (nth (random (length l)) l)))
      (cons element (randomize-list (remove element l)))
    )
  )
)

(defun depth-search (state)
  (let ((offsets '((1 0) (0 1) (-1 0) (0 -1))) offset destination yumchak i j return-value state2 pit)
    (if (equal (first state) (fifth state))
      t
      (dolist (offset (randomize-list offsets))
(format t "~%>>~A ~A<<" (first state) offset)
;	(setq return-value nil)
        (setq destination (mapcar #'+ offset (first state)))
        (if (allowed state (first state) destination)
  	  (progn
	    (setq state2 (copy-tree state))
	    (setf (first state2) destination)
	    (if (dotimes (j (length (second state2)) t)
		  (decf (third (nth j (second state2))))
	          (dolist (i '(1 2))
		    (if (<= (third (nth j (second state2))) 0) (progn
	              (setq yumchak (nth j (second state2)))
	              (cond
		        ((and
		          (< (first yumchak) (first (first state2)))
		          (allowed state2 yumchak (list (+ 1 (first yumchak)) (second yumchak))))
			 (incf (first (nth j (second state2)))))
		        ((and
		          (> (first yumchak) (first (first state2)))
		          (allowed state2 yumchak (list (- (first yumchak) 1) (second yumchak))))
			 (decf (first (nth j (second state2)))))
		        ((and
		          (< (second yumchak) (second (first state2)))
		          (allowed state2 yumchak (list (first yumchak) (+ 1 (second yumchak)))))
			 (incf (second (nth j (second state2)))))
		        ((and
		          (> (second yumchak) (second (first state2)))
		          (allowed state2 yumchak (list (first yumchak) (- (second yumchak) 1))))
			 (decf (second (nth j (second state2)))))
	              )
		      (dolist (pit (third state2) t)
	                (if (equal (subseq (nth j (second state2)) 0 2) pit) (progn (print 'pozo)
	                  (setf (third (nth j (second state2))) 4)))         )
		    ))
	          )
	          (if (equal (first state2) (subseq (nth j (second state2)) 0 2))
(progn (print 'yumchak) (return nil)))
;		    (return nil))
	        )
;(progn (break)
	        (setq return-value (depth-search state2))
;(break))
            )
	    (if return-value (return (cons (first state) return-value)))
	  )))
    )
  )
)

; (wappo (yumchaks) (pits) (walls) (exit))
(let (state)
  (setq level1 '((3 4) ((5 4 0)) ((1 4)) ((1 3 1 4) (3 4 3 5) (5 4 5 5) (5 4 4 4) (5 0 4 0)) (3 0)))
  (setq level2 '((4 1) ((5 0 0)) ((2 4)) ((0 0 0 1) (1 0 1 1) (4 0 4 1) (3 1 3 2) (0 3 0 4)) (1 0)))
  (setq level3 '((5 0) ((3 3 0)) ((3 1) (5 2)) ((0 0 1 0) (1 0 2 0) (3 0 4 0) (3 0 3 1) (4 0 4 1) (3 1 3 2) (3 2 3 3) (2 2 2 3) (0 3 1 3) (2 4 2 5) (4 4 4 5) (4 4 3 4)) (2 0)))
;  (trace depth-search)
  (print (depth-search level3))
)

3 diciembre 2011

Comprobar memoria sin reiniciar (Unix)

Archivado en: Uncategorized — Etiquetas: , , , — thisisoneball @ 12:35

memtester es un programa para Unix al estilo de memtest86 o memtest86+ pero corre en espacio de usuario, es decir, es un programa normal y corriente que se instala en el S.O.
Esto tiene el inconveniente de que no se puede comprobar toda la memoria, solo la que esté libre, pero se puede comprobar la mayor parte. La ventaja es que funciona en cualquier equipo en el que tengas ya un Unix instalado (memtest86 por ejemplo solo funciona en x86), que no hay que reiniciar el equipo y que se puede hacer en remoto.
Como referencia, me ha tardado 7 horas en comprobar 7.5 GB de memoria DDR2-533 en un Itanium 9120N

6 septiembre 2011

Compilar mysql-udf-regexp en RHEL 6 x86_64

Archivado en: Uncategorized — Etiquetas: , , , , , , — thisisoneball @ 21:14

Instrucciones para compilar las UDFs de expresiones regulares de https://launchpad.net/mysql-udf-regexp en RHEL 6 para x86_64

En la web no proporcionan ningún archivo donde se pueda bajar todo el paquete con las fuentes. Sugieren ejecutar el comando

bzr branch lp:mysql-udf-regexp

pero a mí no me funcionaba, solo me funcionó de esta manera:

bzr branch http://bazaar.launchpad.net/~vcs-imports/mysql-udf-regexp/trunk

En mi red tengo que salir a través de un proxy, y bzr requiere proxy HTTP y HTTPS, así que tuve que configurarlo en las variables de entorno http_proxy y https_proxy, instalar el paquete “bzr”, que viene en el repositorio principal de RHEL6, y ejecutar el comando anterior.

Esto deja las fuentes del proyecto en el directorio ./trunk/regexp

El programa requiere las fuentes de Mysql, o al menos los archivos include (.h) de éste para poder compilar. Si has instalado Mysql desde fuentes deberías tener estos archivos. En mi caso tengo instalado el paquete de binarios, pero he podido bajar el paquete de fuentes correspondiente a la misma versión de Mysql que tengo instalada, y ha funcionado.

Pero no basta con los ficheros .h del paquete de ficheros fuente, también necesita otros del paquete de binarios, sobre todo porque esa es la versión que se está ejecutando en el sistema, y contiene información de cómo está configurado el servidor. El script ./configure solo deja especificar uno de estos dos directorios, con la opcion --with-mysql-src, así que la única manera de especificar ambos que he encontrado es

(/usr/local/percona es donde está instalado el paquete de binarios, y /usr/local/Percona-Server-5.1.54-rel12.5 el de fuentes):

CFLAGS='-I/usr/local/percona/include/mysql' ./configure --with-mysql-src=/usr/local/Percona-Server-5.1.54-rel12.5

CFLAGS='-I/usr/local/percona/include/mysql' make

De esta manera ya compila, solo falta instalar la biblioteca. Por alguna razón la crea en un directorio oculto llamado .libs

Una forma de instalarlo es copiar la biblioteca dinámica al directorio plugin de Mysql:

cp .libs/regexp.so /usr/local/percona/lib/mysql/plugin/

Y crear las funciones en Mysql:


CREATE FUNCTION regexp_like RETURNS INTEGER SONAME "regexp.so";
CREATE FUNCTION regexp_substr RETURNS STRING SONAME "regexp.so";
CREATE FUNCTION regexp_instr RETURNS INTEGER SONAME "regexp.so";
CREATE FUNCTION regexp_replace RETURNS STRING SONAME "regexp.so";

13 mayo 2011

Detecting charsets with recode

Archivado en: Uncategorized — Etiquetas: , , — thisisoneball @ 13:07

- source.txt is the file containing unreadable characters
- ‘Ñ’ is one character that we now that appears inside source.txt and is not readable
- recode is a free program that translates text between different encodings

This just tries to recode source.txt using every encoding supported by recode, then checks the recoded file for the special character, if it is found, it means that the character was recoded correctly, so it prints the name of the encoding

for a in $(recode --list | cut -f1 -d\ )
do
    if recode $a < source.txt 2> /dev/null | grep 'Ñ' > /dev/null
    then
       echo $a
    fi
done

8 abril 2011

Parallel grep on a single file

Archivado en: Uncategorized — Etiquetas: , , — thisisoneball @ 12:24

I have a very large text file which I need to grep a lot of times, and it takes 4 minutes. The grep command only uses one core, so it could take much less time if I parallelize the command.

If you have GNU Parallel this will do the trick (tested on Linux and Cygwin):

$ cat dump.sql | parallel -k --pipe grep -i pattern

This is a different method, using xargs, which is present in most Unices, but it uses temporary files (the original file splitted).

This command splits the big file into 6 smaller ones, as I want to use 6 cores in parallel. The -C switch limits the size of each splitted file, and ensures that no lines are splitted between one file and the next one, the split will always occur at the end of one line:

$ split -C 320000000 dump.sql
 -rw-r--r--. 1 bd users 319999897 Apr 7 16:55 xaa
 -rw-r--r--. 1 bd users 319999939 Apr 7 16:55 xab
 -rw-r--r--. 1 bd users 319999801 Apr 7 16:55 xac
 -rw-r--r--. 1 bd users 319999988 Apr 7 16:55 xad
 -rw-r--r--. 1 bd users 319999595 Apr 7 16:55 xae
 -rw-r--r--. 1 bd users 308677345 Apr 7 16:55 xaf

And this command runs one grep process for each of the splitted files:

$ ls xa* | xargs -P 6 -n 1 grep -i 'pattern'

For differences between this kind of programs, see the Parallel man page

1 marzo 2011

RRDs.pm / perl-rrdtool for RHEL 6 x86_64

Archivado en: Uncategorized — Etiquetas: , — thisisoneball @ 21:26

If you’re looking for the file RRDs.pm for Red Hat Enterprise Linux 6, as far as I know it’s not included in the official Red Hat packages or in the EPEL ones (there is a rrdtool package but not a perl-rrdtool one)

I downloaded and compiled the sources for the whole rrdtool program, the same version that comes with RHEL 6, and uploaded just the necessary files for RRDs.pm: (rename the file to .tar.gz)

perl-rrd-1.3.8-rhel6.tar.gz

22 noviembre 2010

Upload multiple files to tumblr

Archivado en: Uncategorized — Etiquetas: , — thisisoneball @ 19:13

This is an example of a photo upload using the Tumblr API and cURL:

curl -s -F "email=me@hotmail.com" -F "password=mypass" -F "type=photo" -F "tags=tag1,tag2" \
-F "data=@picture.jpg"  http://www.tumblr.com/api/write

If nothing goes wrong, this will print the tumblr post ID of the post you have just created.

See here for other parameters that you can change or add to that command (queuing the post, setting a caption, uploading different types of content …)

This is a simple bash script that uploads all the JPG files in the current folder, in a random order, adding them to your tumblr queue (instead of posting them now):

IFS=$'\n'     # needed if the jpg filenames contain spaces (restore the value later with  IFS=$' \t\n'  or close the terminal)

for file in $(ls *.JPG *.jpg | shuf)       # shuf randomizes the jpg filenames
do
echo $file
curl -s -F "email=me@hotmail.com" -F "password=mypass" -F "type=photo" -F "state=queue"  \
-F "data=@$file"  http://www.tumblr.com/api/write
echo
sleep 5s                               # waits between uploads
done

12 noviembre 2010

Servidores SSH gratuitos para Windows

Archivado en: Uncategorized — thisisoneball @ 01:02

Basados en Cygwin y OpenSSH:

- Cygwin + paquete OpenSSH
Probablemente la mejor opción pero la más complicada de instalar. Recomendable si ya tenías una instalación de Cygwin en esa máquina.
Está bien actualizada y una vez que haces el login remoto tienes disponibles todas las utilidades de Cygwin, y esto es muy útil ya que por SSH solo puedes usar comandos de texto.
Aparte del servidor, trae los clientes ssh.exe y scp.exe, útiles para acceder a otros servidores SSH desde línea de comandos, y para hacer pruebas con el servidor local.
- copssh y sshwindows
También están basadas en Cygwin y en OpenSSH, y de hecho pueden dar problemas si tienes ya Cygwin instalado.
Lo bueno es que es más cómodo de instalar que la opción anterior. Es el típico instalador, por lo que es útil para una máquina sin acceso a Internet.
sshwindows está bastante desactualizada, y esto puede ser bastante peligroso sobre todo si tu servidor SSH va a estar abierto a Internet.

Servidores nativos para Windows, no utilizan Cygwin:

http://www.freesshd.com/
http://mobassh.mobatek.net/en/
http://www.bitvise.com/winsshd

Se agradecen sugerencias de otros programas y opiniones si usáis alguna de las opciones anteriores (por ejemplo si soporta SCP, SFTP, túneles, …)

Puede que para un servidor Windows sea más conveniente un escritorio remoto tipo VNC, ya que son gráficos y también permiten transferir archivos. Las ventajas de usar SSH son:
- Permite tunelizar conexiones y hacer port forwarding
- Las transferencias de archivos se pueden utilizar con clientes típicos como Filezilla o WinSCP
- Es cómodo para ejecutar comandos en el servidor o transferir archivos de forma no interactiva, por ejemplo desde scripts o desde un programador de tareas

21 agosto 2010

Cómo comprar billetes de ALSA sin comisión

Archivado en: Uncategorized — thisisoneball @ 17:35

Si utilizas regularmente los autobuses de ALSA sabrás que cobran una comisión muy alta por comprar los billetes por internet (p.ej. 2,50 euros por un billete de 16,30 euros).  Éstas son las formas de comprar un billete sin pasar por la taquilla:

  • www.movelia.es: 2,50 euros de comisión (“gastos de gestión” según ellos)
  • www.alsa.es: 1 euro para compras inferiores a 10 euros; 2,50 euros para compras superiores a 10 euros.
  • Cajeros de La Caixa: creo que 2 euros de comisión. Útil si no tienes conexión a Internet y no tienes cerca una taquilla de Alsa.
  • Tarjeta Bus Plus de Alsa: permite comprar en www.alsa.es sin comisión. Es una tarjeta monedero, en la cual cargas dinero y luego al comprar el billete te coge el dinero de ahí. Se saca y se recarga en las taquillas de Alsa. Aparte de la comisión también tiene otras ventajas:
    • Te da descuentos cuanto más dinero cargues:

más de 100 euros: 5%
más de 200 euros: 10%
más de 300 euros: 15%
más de 500 euros: 20%

Según la web, cuanto más cargues en la tarjeta mayor descuento obtendrás. Pero esto no funciona como parece, de hecho puede que cargando más dinero en la tarjeta tu descuento se vea reducido.
Por ejemplo: Cargas 200 euros, el descuento es de 10%. Después de hacer algunos viajes, tu saldo ha bajado a 150 euros. Entonces cargas otros 100 euros, y te quedan 250. Lo lógico es que tu descuento siga en el 10%, pero en realidad te ha bajado, ya que la carga de 100 euros supone un descuento del 5%, y hacen la media entre el 10% y el 5%

Por lo tanto lo que deberías haber hecho es cargar 200 euros, gastarlos completamente, y entonces cargar los 100 euros. Pregunta por si acaso en la taquilla cuando vayas a cargarlo. 

  •  
    • Si pierdes el autobús puedes ir a la taquilla de la estación en la media hora siguiente y te darán plaza en el siguiente, si quedan plazas.
    • Puedes usar la tarjeta para comprar billetes para cualquier persona. Por lo tanto puede ser interesante cargarla entre varias personas y coger todos los billetes con ella (para comprar un billete solo hace falta el número de la tarjeta y el NIF del titular).
    • Te envían el número de localizador en un SMS, junto con otros datos del viaje. No hace falta imprimir nada, con dar el número o tu nombre al conductor suele valer, o en todo caso puede pedirte el DNI.
    • En dos ocasiones me han cobrado un viaje 2 veces. Recomiendo vigilar el saldo de vez en cuando (lo puedes ver en la página de Alsa en la sección Mi Bus Plus. Lo gestioné por e-mail y me devolvieron el dinero sin problemas.
    • Recuerda desmarcar la casilla del Seguro de viaje al comprar cada billete, a no ser que quieras el seguro. Es 1 euro más por trayecto.

28 octubre 2009

Copiar tablas / crear tablas con una SELECT / Copy tables

Archivado en: Uncategorized — Etiquetas: , , , , — thisisoneball @ 01:37

Hay varias formas diferentes de copiar una tabla rápidamente, en una sola consulta SQL. Evitan tener que hacer un CREATE TABLE especificando todos los nombres y tipos de datos de los campos. No obstante sólo copian los campos, no los índices ni las constraints. Esta es una comparativa de ellas y los SGBD en los que funciona cada una:

Consulta Mysql Postgres Oracle Access Copia estructura Copia datos
CREATE TABLE destino AS SELECT * FROM origen Si Si Si No Si Si
CREATE TABLE destino LIKE origen Si** Si No No Si No
INSERT INTO destino SELECT * FROM origen Si Si Si Si No Si
SELECT * INTO destino FROM origen No Si* No Si Si Si

* La documentación de Postgres recomienda usar CREATE TABLE AS mejor que SELECT INTO

** En MySQL esta instrucción copia todas las características de la tabla origen, incluidos los índices, comentarios, … Por lo tanto para hacer una copia idéntica lo mejor es CREATE TABLE destino LIKE origen + INSERT INTO destino SELECT * FROM origen

Esto también puede servir para copiar tablas entre distintos esquemas. Por ejemplo en MySQL:

CREATE TABLE esquema2.tabla AS SELECT * FROM esquema1.tabla;

Entradas más antiguas »

Tema Shocking Blue Green. Blog de WordPress.com.

Seguir

Get every new post delivered to your Inbox.