;;; 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)))))