All pastes #765852 Raw Edit

Mine

public text v1 · immutable
·published 2007-11-08 12:22 UTC
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)))))