rendered paste body;;; practica-2.lsp
;;; Ejercicios de arrays, bucles, estructuras y tablas hash
;;; --------------------------------------------------------
;;; (1) Definir una funcion mostrar-tablero para mostrar por pantalla
;;; el contenido de un array como se muestra en el ejemplo.
;;;
;;; Ejemplo:
;;; Definimos un tablero previamente:
;;; > (setf *tablero*
;;; (make-array '(3 3)
;;; :initial-contents '((1 2 3)
;;; (4 5 6)
;;; (7 8 9))))
;;; ...
;;; > (mostrar-tablero *tablero*)
;;; [ 1 2 3 ]
;;; [ 4 5 6 ]
;;; [ 7 8 9 ]
;;;NIL
(setf *tablero*
(make-array '(3 3)
:initial-contents '((1 2 3)
(4 5 6)
(7 8 9))))
(defun mostrar-tablero (tablero)
(let*
(
(dim (array-dimensions tablero))
(d1 (- (nth 0 dim) 1) )
(d2 (- (nth 1 dim) 1) )
)
(loop for i from 0 to d1 do
(let ()
(format t "[ ")
(loop for j from 0 to d2 do
(format t "~a " (aref tablero i j))
)
(format t "]~%")
)
)
)
)
;;;
;;; (2) Definir la accion de "Disparo simple" sobre una casilla de un
;;; tablero que se supondra cuadrado. El valor de disparar a una
;;; casilla es el valor almacenado en esa casilla. Como efecto colateral
;;; lo deja a 0 tras el disparo.
;;; Ejemplo:
;;; ;dado *tablero*
;;; ;[ 1 2 3 ]
;;; ;[ 4 7 6 ]
;;; ;[ 7 8 9 ]
;;;
;;; > (disparar-casilla *tablero* 0 0)
;;; 1
;;; > (mostrar-tablero *tablero*)
;;; [ 0 2 3 ]
;;; [ 4 7 6 ]
;;; [ 7 8 9 ]
;;; NIL
(defun disparar-casilla (tablero i j)
(let
(
(valor (aref tablero i j))
)
(setf (aref tablero i j) 0)
valor
)
)
;;; (3) Supongamos que representamos un disparo simple mediante las
;;; coordenadas de la posicion en la que se efectua. Por ejemplo '(2 4)
;;; representa un disparo en la posicion (2 4) del tablero.
;;;
;;; Definir la funcion puntuacion-total que recibiendo como entrada un
;;; tablero inicial y una secuencia de acciones como las descritas,
;;; calcule la suma de puntos obtenidos por la secuencia de acciones (y
;;; que como efecto colateral modifique el tablero consecuentemente).
;;; Ejemplo:
;;; > (puntuacion-total *tablero* '((0 0) (1 2) (2 1) (1 1)))
;;; 20
;;; > (mostrar-tablero *tablero*)
;;; [ 0 2 3 ]
;;; [ 4 0 0 ]
;;; [ 7 0 9 ]
;;; NIL
(defun puntuacion-total (tablero l)
(loop for x in l summing
(disparar-casilla tablero (nth 0 x) (nth 1 x))
)
)
;;; (4) Queremos ahora tener la informacion de cada tirador, para ello
;;; se ha pensado definir una estructura que contenga lo siguiente:
;;; - nombre del tirador
;;; - puntuacion global que acumula (inicialmente a 0)
;;; - disparos realizados (inicialmente la lista vacia)
;;; - tablero actual sobre el que dispara (inicialmente un tablero 5x5
;;; con el siguiente contenido):
;;;
;;; ((1 2 3 2 1)
;;; (2 4 6 4 2)
;;; (4 8 16 8 4)
;;; (2 4 6 4 2)
;;; (1 2 3 2 1))
;;;
;;;
;;; Ejemplo: (tras crear la estructura sera posible definir tiradores como)
;;; > (make-tirador :nombre "Black Hunter")
;;; #S(TIRADOR :NOMBRE "Black Hunter" :PUNTUACION 0
;;; :TABLERO #2A((0 0 0) (0 0 0) (0 0 0)) :DISPAROS NIL)
;;; #S(TIRADOR :NOMBRE "Black Hunter" :PUNTUACION 0
;;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;;; :DISPAROS NIL)
;;; > (make-tirador :nombre "Princess Leia" :puntuacion 100)
;;; #S(TIRADOR :NOMBRE "Princess Leia" :PUNTUACION 100
;;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;;; :DISPAROS NIL)
(defstruct tirador
nombre
(puntuacion 0)
(disparos ())
(tablero
(make-array '(5 5)
:initial-contents
'((1 2 3 2 1)
(2 4 6 4 2)
(4 8 16 8 4)
(2 4 6 4 2)
(1 2 3 2 1))
)
)
)
;;; (5) Dado un listado de tiradores se quiere ordenar de menor a mayor
;;; puntuacion los tiradores.
;;;
;;; Ejemplo:
;;; ;Definimos algunos tiradores
;; > (setf *tirador1*
;; (make-tirador :nombre "Black Hunter" :puntuacion 15))
;; > (setf *tirador2*
;; (make-tirador :nombre "Princess Leia"))
;; > (setf *tirador3*
;; (make-tirador :nombre "Han Solo" :puntuacion 200))
;;
;; > (ordenar-tiradores (list *tirador1* *tirador2* *tirador3*))
;;; (#S(TIRADOR :NOMBRE "Han Solo" :PUNTUACION 200
;;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;;; :DISPAROS NIL)
;;; #S(TIRADOR :NOMBRE "Black Hunter" :PUNTUACION 15
;;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;;; :DISPAROS NIL)
;;; #S(TIRADOR :NOMBRE "Princess Leia" :PUNTUACION 0
;;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;;; :DISPAROS NIL))
(defun ordenar-tiradores (l)
(sort l
#'(
lambda (a b)
(> (tirador-puntuacion a) (tirador-puntuacion b))
)
)
)
;;; (6) Para mantener la informacion de cada tirador y acceder a ella de
;;; manera eficiente mediante nick o apodo, se usara una tabla hash cuya
;;; clave sea el apodo y el valor de cada clave sea la estructura que
;;; representa el correspondiente tirador.
;;; Por ejemplo:
(defparameter *tiradores-sw* (make-hash-table))
;;; Definir funciones para realizar las siguientes acciones:
;;; (6.1) Definir una funcion (alta nick nombre tabla) para dar de alta
;;; aportando el nick y su nombre real. La estructura debe ser creada
;;; con los valores por defecto anteriormente mencionados. Si ya
;;; existiera alguien con ese nick, devolver el correspondiente mensaje
;;; de error.
;;; Ejemplos:
;; > (alta 'blacky "Black Hunter" *tiradores-sw*)
;; ...
;; > (alta 'han "Han Solo" *tiradores-sw*)
;; ...
;; > *tiradores-sw*
;; #S(HASH-TABLE EQL
;; (HAN .
;; #S(TIRADOR :NOMBRE "Han Solo" :PUNTUACION 0
;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS NIL))
;; (BLACKY .
;; #S(TIRADOR :NOMBRE "Black Hunter" :PUNTUACION 0
;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS NIL)))
;; > (alta 'han "Han Solo" *tiradores-sw*)
;; Ya existe un tirador con el nick HAN
;; > (alta 'han "Hanna")
;; Ya existe un tirador con el nick HAN
;;; (7.2) Definir una funcion (baja nick tiradores) para dar de baja a
;;; un tirador de la tabla de tiradores. Si no existiera alguien con ese
;;; nick, devolver el correspondiente mensaje de error.
;;; Ejemplo:
;;; > (baja 'blacky *tiradores)
;;; T
;;; > *tiradores-sw*
;;; #S(HASH-TABLE EQL
;;; (HAN .
;;; #S(TIRADOR :NOMBRE "Han Solo" :PUNTUACION 0
;;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;;; :DISPAROS NIL)))
;;; > (baja 'blacky *tiradores-sw*)
;;; No existe un tirador con el nick BLACKY
;;; (7.3) Definir una funcion (actualiza nick secuencia tiradores) que
;;; actualiza el registro de un tirador modificando el tablero para
;;; reflejar los cambios en el mismo tras una secuencia de
;;; disparos. Tambien hay que modificar la puntuacion para acumular la
;;; puntuacion obtenida en dicha secuancia y la secuencia total de
;;; disparos. Supondremos, por simplificar, que el nick siempre esta
;;; dado de alta en la tabla de tiradores cuando se llama a esta
;;; funcion.
;;; Ejemplo:
;; > *tiradores-sw*
;; #S(HASH-TABLE EQL
;; (HAN .
;; #S(TIRADOR :NOMBRE "Han Solo" :PUNTUACION 0
;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS NIL))
;; (BLACKY .
;; #S(TIRADOR :NOMBRE "Black Hunter" :PUNTUACION 0
;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS NIL)))
;; > (actualiza 'blacky '((1 0) (0 1)) *tiradores-sw*)
;; ...
;; > (actualiza 'han '((2 2) (2 1) (2 1) (1 0)) *tiradores-sw*)
;; ...
;; > (actualiza 'blacky '((0 0) (1 1)) *tiradores-sw*)
;; ...
;; > *tiradores-sw*
;; #S(HASH-TABLE EQL
;; (HAN .
;; #S(TIRADOR :NOMBRE "Han Solo" :PUNTUACION 26
;; :TABLERO #2A((1 2 3 2 1) (0 4 6 4 2) (4 0 0 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS ((2 2) (2 1) (2 1) (1 0))))
;; (BLACKY .
;; #S(TIRADOR :NOMBRE "Black Hunter" :PUNTUACION 9
;; :TABLERO #2A((0 0 3 2 1) (0 0 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS ((1 0) (0 1) (0 0) (1 1)))))
;;; (7.4) Definir una funcion (reiniciar nick tiradores) que reinicia a
;;; los valores iniciales la informacion de un tirador. Supondremos, por
;;; simplificar, que el nick siempre esta dado de alta en la tabla de
;;; tiradores cuando se llama a esta.
;;; Ejemplos:
;; > (reiniciar-nick 'blacky *tiradores-sw*)
;; ...
;; > (reiniciar-nick 'han *tiradores-sw*)
;; ...
;; > *tiradores-sw*
;; #S(HASH-TABLE EQL
;; (HAN .
;; #S(TIRADOR :NOMBRE "Han Solo" :PUNTUACION 0
;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS NIL))
;; (BLACKY .
;; #S(TIRADOR :NOMBRE "Black Hunter" :PUNTUACION 0
;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS NIL)))
;;; (7.5) Definir (mostrar-clasificacion tiradores) que muestra por
;;; pantalla una clasificacion ordenada de los tiradores, segun la
;;; puntuacion que tengan.
;;; Ejemplo:
;; > *tiradores-sw*
;; #S(HASH-TABLE EQL
;; (PRINCESA .
;; #S(TIRADOR :NOMBRE "Princess Leia" :PUNTUACION 0
;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS NIL))
;; (HAN .
;; #S(TIRADOR :NOMBRE "Han Solo" :PUNTUACION 26
;; :TABLERO #2A((1 2 3 2 1) (0 4 6 4 2) (4 0 0 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS ((2 2) (2 1) (2 1) (1 0))))
;; (BLACKY .
;; #S(TIRADOR :NOMBRE "Black Hunter" :PUNTUACION 9
;; :TABLERO #2A((0 0 3 2 1) (0 0 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS ((0 0) (1 1) (1 0) (0 1)))))
;; > (mostrar-clasificacion *tiradores-sw*)
;; Han Solo 26
;; Black Hunter 9
;; Princess Leia 0
;;; (8) Se desean definir las siguientes acciones adicionales sobre un
;;; tablero, que se supondra cuadrado.
;;; (8.1) "Disparo extra" sobre la casilla: al disparar sobre una
;;; casilla se devuelve la suma de los valores que aparecen en la fila y
;;; en la columna en las que esta ese valor, y como efecto colateral
;;; se modifica la matriz de entrada colocando un cero en toda esa fila y
;;; en toda esa columna. Si la casilla ya estuviera a cero, devolver
;;; cero y no modificar la matriz.
;;; Ejemplos:
;;; > (setf *tablero* (make-array '(3 3) :initial-contents '((1 2 3) (4 5 6) (7 8 9))))
;;; ....
;;; > (disparar-extra *tablero* 1 1)
;;; 25
;;; > (mostrar-tablero *tablero*)
;;; [ 1 0 3 ]
;;; [ 0 0 0 ]
;;; [ 7 0 9 ]
;;; NIL
;;; (8.2) Rotacion del tablero: la funcion devuelve el valor -10 y
;;; como efecto colateral el tablero de entrada se transforma rotando 90
;;; grados en el sentido de las agujas del reloj.
;;; Ejemplos:
;; > (mostrar-tablero *a*)
;; [ 1 2 3 4 5 ]
;; [ 6 7 8 9 10 ]
;; [ 11 12 13 14 15 ]
;; [ 16 17 18 19 20 ]
;; [ 21 22 23 24 25 ]
;; NIL
;; > (rotar *a*)
;; -10
;; > (mostrar-tablero *a*)
;; [ 21 16 11 6 1 ]
;; [ 22 17 12 7 2 ]
;; [ 23 18 13 8 3 ]
;; [ 24 19 14 9 4 ]
;; [ 25 20 15 10 5 ]
;; NIL
;; > (rotar *a*)
;; -10
;; > (mostrar-tablero *a*)
;; [ 25 24 23 22 21 ]
;; [ 20 19 18 17 16 ]
;; [ 15 14 13 12 11 ]
;; [ 10 9 8 7 6 ]
;; [ 5 4 3 2 1 ]
;; NIL
;;; (9) Representaremos estas acciones adicionales definidas en el
;;; ejercicio anterior de la siguiente manera:
;;; - Un disparo extra se representara mediante una lista cuyo unico
;;; elemento es una lista de dos elementos indicando la posicion. Por
;;; ejemplo ((2 4)) representa un disparo extra en la posicion (2 4)
;;; - El simbolo 'rotar representara la accion de rotar.
;;; Realizar las modificaciones pertinentes para que la funcion
;;; actualiza del ejercicio (7.3) permita en su secuencia de
;;; acciones, ademas de disparos simples, disparos extras y
;;; rotaciones. �Cuantas funciones hay que modificar?
;;; Ejemplo:
;; > *tiradores-sw*
;; #S(HASH-TABLE EQL
;; (PRINCESA .
;; #S(TIRADOR :NOMBRE "Princess Leia" :PUNTUACION 0
;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS NIL))
;; (HAN .
;; #S(TIRADOR :NOMBRE "Han Solo" :PUNTUACION 0
;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS NIL))
;; (BLACKY .
;; #S(TIRADOR :NOMBRE "Black Hunter" :PUNTUACION 0
;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS NIL)))
;; > (actualiza 'blacky '((1 0) ((3 3)) (2 3) rotar ((0 0))) *tiradores-sw*)
;; ((1 0) ((3 3)) (2 3) ROTAR ((0 0)))
;; > (actualiza 'han '(((2 1)) rotar (2 1) ((2 1))) *tiradores-sw*)
;; (((2 1)) ROTAR (2 1) ((2 1)))
;; > (actualiza 'blacky '(rotar (4 1)) *tiradores-sw*)
;; ((1 0) ((3 3)) (2 3) ROTAR ((0 0)) ROTAR (4 1))
;; > *tiradores-sw*
;; #S(HASH-TABLE EQL
;; (PRINCESA .
;; #S(TIRADOR :NOMBRE "Princess Leia" :PUNTUACION 0
;; :TABLERO #2A((1 2 3 2 1) (2 4 6 4 2) (4 8 16 8 4) (2 4 6 4 2) (1 2 3 2 1))
;; :DISPAROS NIL))
;; (HAN .
;; #S(TIRADOR :NOMBRE "Han Solo" :PUNTUACION 48
;; :TABLERO #2A((1 2 0 2 1) (0 0 0 0 0) (3 0 0 6 3) (2 4 0 4 2) (1 2 0 2 1))
;; :DISPAROS (((2 1)) ROTAR (2 1) ((2 1)))))
;; (BLACKY .
;; #S(TIRADOR :NOMBRE "Black Hunter" :PUNTUACION 28
;; :TABLERO #2A((0 0 0 0 0) (0 0 0 0 0) (4 0 16 8 0) (2 0 6 4 0) (1 0 3 2 0))
;; :DISPAROS ((1 0) ((3 3)) (2 3) ROTAR ((0 0)) ROTAR (4 1)))))