Sera OT??

Horst von Brand vonbrand en inf.utfsm.cl
Mar Abr 27 22:18:41 CLT 2004


Roberto Bonvallet <rbonvall en inf.utfsm.cl> dijo:
> Arturo Mardones escribio:
> > Tengo q hacer un programa para "resolver" el problema del vendedor
> > viajero (con heuristica claro esta)... Y no se q lenguaje utilizar... 

> Eso es OT. Para no estar (tan) OT, se me ocurrio programar una
> heuristica en Bash; si te decides por alguna shell Unix, esto te puede
> ser de ayuda. Puedes usar esta matriz como entrada para probarla con 6
> ciudades (copiala en un archivo y se lo pasas al programa)
> 
> 24 22 23 17 25
>    21 33 15 24
>       26 24 27
>          23 21
>             19

Esa es mi clase preferida de demente!

> He aqui el script:
> 
> #!/bin/bash
> 
> # Implementación de la heurística Nearest Neighbor 
> # para el problema del vendedor viajero
> # 20040427 by rbonvall
> 
> # uso: tsp -c nro_ciudades -d archivo_distancias
> 
> # Si dij es la distancia entre las ciudades i y j,
> # archivo_distancias tiene el siguiente formato:
> # d12 d13 d14 ... ... d1n
> # d23 d24 d25 ... d2n
> # .
> # :
> # d(n-2)(n-1) d(n-2)n
> # d(n-1)n
> 
> # mensaje de error de uso
> uso="Uso: $0 -c nro_ciudades -d archivo_distancias"
> # distancia máxima imposible entre ciudades
> infinito=999999
> # archivo temporal

mktemp(1)

> temp=/tmp/tmp$$
> if [ -f $temp ]
> then
>     rm -f $temp
> fi
> touch $temp
> 
> # parsea argumentos
> c_flag=
> d_flag=
> set -- $(getopt c:d: "$@")
> [ $# -lt 1 ] && exit 1  # getopt failed
> while [ $# -gt 0 ]
> do
>     case "$1" in
>         -c) 
>             nro_ciudades="$2"
>             c_flag=1
>             shift
>         ;;
>         -d)
>             archivo_distancias="$2"
>             if [ -f $archivo_distancias ]
>             then
>                 distancias=$(cat $archivo_distancias)

                  distancias=$(< $archivo_distancias)

(Mas eficiente, segun bash(1))

>             else
>                 echo "No existe el archivo $archivo_distancias"
>                 exit 1
>             fi
>             d_flag=1
>             shift
>         ;;
>         *) 
>             break
>         ;;
>     esac
>     shift
> done
> if ! [ $c_flag ] || ! [ $d_flag ]
> then
>     echo >&2 $uso
>     exit 1
> fi
> 
> inicial=1   # ciudad desde la que se iniciará el ciclo
> actual=$inicial  # ciudad en la que va el ciclo
> 
> # iteramos hasta que en el archivo de salida estén todas las ciudades
> while [ $(wc -l $temp| sed -e 's/^[ ]*//g'| cut -d' ' -f 1) -lt $nro_ciudades ]
> do
>     echo "Ciudad actual: $actual"
>     # agrega ciudad actual al ciclo
>     echo $actual >> $temp
>     # inicializa mínima distancia y ciudad más cercana
>     min_dist=$infinito
>     ciudad_mas_cercana=
>     # busca vecina más cercana
>     for vecina in $(seq $nro_ciudades)
>     do
>         # determina qué ciudad tiene número menor para 
>         # saber cómo buscar la distancia en el archivo
>         if [ $vecina -lt $actual ]
>         then
>             max=$actual
>             min=$vecina
>         elif [ $vecina -gt $actual ]
>         then
>             max=$vecina
>             min=$actual
>         fi
>         
>         if ! [ "$(grep "$vecina" $temp)" ] # evitamos ciudades ya visitadas
>         then
>             # calcula la distancia entre la ciudad actual y la vecina
>             dist=$(awk "NR == $min { print \$($max - $min) }" < $archivo_distancias)
>             echo "Distancia de $actual a $vecina: $dist"
>             # determina si esta vecina es la más cercana
>             if [ $dist -le $min_dist ]
>             then
>                 min_dist=$dist
>                 ciudad_mas_cercana=$vecina
>             fi
>         fi
>     done
>     echo "Ciudad más cercana a $actual: $ciudad_mas_cercana"
> 
>     # nos movemos a la vecina más cercana
>     actual=$ciudad_mas_cercana
> done
> 
> echo "El ciclo es:"
> cat $temp
> rm $temp

Ahora falta en ex(1)... emacs LISP es demasiado simple ;-)
-- 
Dr. Horst H. von Brand                   User #22616 counter.li.org
Departamento de Informatica                     Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria              +56 32 654239
Casilla 110-V, Valparaiso, Chile                Fax:  +56 32 797513


Más información sobre la lista de distribución Linux