~herlock_sholmes/PensamientoComputacional

12327b653b78f32236babed0257116ee8f19d79d — Camilo Meza Gaete 5 months ago d9264a3 master
0027: Se añade el juego Snake

Y algunas modificaciones menores que se hicieron en vivo en otros archivos.
M EjemplosRacket/Juegos/GUIAdivinaElNumero/source.rkt => EjemplosRacket/Juegos/GUIAdivinaElNumero/source.rkt +2 -2
@@ 76,13 76,13 @@
;
;

(define TEXT-SIZE 20)
(define TEXT-SIZE 25)
(define HELP-TEXT
  (text "↑ para números mayores, ↓ para menores"
        TEXT-SIZE
        "blue"))
(define HELP-TEXT2
  (text "Presiona = cuando tu número ha sido adivinado; q para salir."
  (text "Presiona = cuando tu número ha sido adivinado\nq para salir."
        TEXT-SIZE
        "blue"))
(define WIDTH (+ (image-width HELP-TEXT2) 20))

A EjemplosRacket/Juegos/Snake/graphics/body.gif => EjemplosRacket/Juegos/Snake/graphics/body.gif +0 -0
A EjemplosRacket/Juegos/Snake/graphics/goo.gif => EjemplosRacket/Juegos/Snake/graphics/goo.gif +0 -0
A EjemplosRacket/Juegos/Snake/graphics/head.gif => EjemplosRacket/Juegos/Snake/graphics/head.gif +0 -0
A EjemplosRacket/Juegos/Snake/graphics/tail.gif => EjemplosRacket/Juegos/Snake/graphics/tail.gif +0 -0
A EjemplosRacket/Juegos/Snake/source.rkt => EjemplosRacket/Juegos/Snake/source.rkt +858 -0
@@ 0,0 1,858 @@
#lang racket

#|
   The Snake game
   --------------
   The Snake game revolves around a room filled with pieces of radioactive goo
   and a snake that can remove this goo.
   When the snake eats the goo, it grows and new goo appears. Like all
   radioactive material, goo decays over time. Eventually it expires, but
   fortunately for the snake, a new piece of goo appears elsewhere.
   The player is in control of a snake, and the objective is to grow the snake as
   large as possible. She may change the direction of the snake by pressing one of
   the four arrow keys. When the snake gets close to a piece of goo, it eats the
   goo and grows a new segment. If the snake runs into itself or one of the four
   walls, the game is over. The length of the snake is the player's score.
   Play
   ----

   Run and evaluate
     (start-snake)
   This will pop up a window with instructions for interacting with the program.
|#

;
;
;
;
;                                 ;;
;     ;;; ;                        ;
;    ;   ;;                        ;
;    ;    ;   ;; ;;;      ;;;;     ;  ;;;     ;;;
;    ;         ;;   ;    ;    ;    ;  ;      ;   ;
;     ;;;;     ;    ;         ;    ; ;      ;     ;
;         ;    ;    ;    ;;;;;;    ;;;      ;;;;;;;
;    ;    ;    ;    ;   ;     ;    ;  ;     ;
;    ;;   ;    ;    ;   ;    ;;    ;   ;     ;    ;
;    ; ;;;    ;;;  ;;;   ;;;; ;;  ;;  ;;;;    ;;;;
;
;
;
;

(require 2htdp/image 2htdp/universe)
;; -----------------------------------------------------------------------------
;; Data Definitions

;; A Pit is a (pit Snake (Listof Goo))
(struct pit (snake goos) #:transparent)

;; A Snake is a (make-snake Direction (cons Seg [Listof Seg]))
(struct snake (dir segs) #:transparent)
;; The head of the snake is the first element in the list of segs.
;; Each segment of a snake is located with:
;;  - x in (0,SIZE),
;;  - y in (0,SIZE).
;; And is SEG-SIZE aligned (x and y are multiples of SEG-SIZE).

;; A Seg is a (posn Number Number)

;; A Goo is a (goo Posn Number)
(struct goo (loc expire) #:transparent)
;; The expire field is a Natural Number that represents the number
;; of ticks until the goo expires. A goo is expired when this field is 1

;; A Direction is one of "up" "down" "left" "right"

;; A Posn is (posn number number)
(struct posn (x y) #:transparent)
;; Represents a two dimensional point.

;; -----------------------------------------------------------------------------
;; Constants

;; Tick Rate
(define TICK-RATE 1/10)

;; Board Size Constants
(define SIZE 30)

;; Snake Constants
(define SEG-SIZE 15)

;; Goo Constants
(define MAX-GOO 5)
(define EXPIRATION-TIME 150)

;; GRAPHICAL BOARD
(define WIDTH-PX  (* SEG-SIZE SIZE))
(define HEIGHT-PX (* SEG-SIZE SIZE))

;; Visual constants
(define MT-SCENE (empty-scene WIDTH-PX HEIGHT-PX))
(define GOO-IMG (bitmap "graphics/goo.gif"))
(define SEG-IMG  (bitmap "graphics/body.gif"))
(define HEAD-IMG (bitmap "graphics/head.gif"))

(define HEAD-LEFT-IMG HEAD-IMG)
(define HEAD-DOWN-IMG (rotate 90 HEAD-LEFT-IMG))
(define HEAD-RIGHT-IMG (flip-horizontal HEAD-LEFT-IMG))
(define HEAD-UP-IMG (flip-vertical HEAD-DOWN-IMG))

(define ENDGAME-TEXT-SIZE 15)


;
;
;
;                          ;
;                          ;
;  ;;;   ;;;
;   ;;   ;;
;   ; ; ; ;     ;;;;     ;;;      ;; ;;;
;   ; ; ; ;    ;    ;      ;       ;;   ;
;   ; ; ; ;         ;      ;       ;    ;
;   ;  ;  ;    ;;;;;;      ;       ;    ;
;   ;     ;   ;     ;      ;       ;    ;
;   ;     ;   ;    ;;      ;       ;    ;
;  ;;;   ;;;   ;;;; ;;  ;;;;;;;   ;;;  ;;;
;
;
;
;
;; -----------------------------------------------------------------------------

;; Start the Game
(define (start-snake)
  (big-bang (pit (snake "right" (list (posn 1 1)))
                 (list (fresh-goo)
                       (fresh-goo)
                       (fresh-goo)
                       (fresh-goo)
                       (fresh-goo)
                       (fresh-goo)))
            (on-tick next-pit TICK-RATE)
            (on-key direct-snake)
            (to-draw render-pit)
            (stop-when dead? render-end)))

;; Pit -> Pit
;; Take one step: eat or slither
(define (next-pit w)
  (define snake (pit-snake w))
  (define goos  (pit-goos w))
  (define goo-to-eat (can-eat snake goos))
  (if goo-to-eat
      (pit (grow snake) (age-goo (eat goos goo-to-eat)))
      (pit (slither snake) (age-goo goos))))

;; Pit KeyEvent -> Pit
;; Handle a key event
(define (direct-snake w ke)
  (cond [(dir? ke) (world-change-dir w ke)]
        [else w]))

;; Pit -> Scene
;; Render the world as a scene
(define (render-pit w)
  (snake+scene (pit-snake w)
               (goo-list+scene (pit-goos w) MT-SCENE)))

;; Pit -> Boolean
;; Is the snake dead?
(define (dead? w)
  (define snake (pit-snake w))
  (or (self-colliding? snake) (wall-colliding? snake)))

;; Pit -> Scene
;; produces a gameover image
(define (render-end w)
  (overlay (text "Game over" ENDGAME-TEXT-SIZE "black")
           (render-pit w)))

;
;
;
;     ;;;;    ;;                    ;;              ;;;;;;     ;            ;;
;    ;   ;     ;                     ;              ;  ;                     ;
;   ;          ;     ;;;;    ;;; ;   ; ;;;;            ;     ;;;     ;;; ;   ; ;;;;  ;;;;;
;   ;          ;    ;    ;  ;;  ;;   ;  ;              ;       ;    ;;  ;;   ;  ;   ;    ;
;   ;          ;    ;    ;  ;        ;;;               ;       ;    ;        ;;;     ;;;;
;   ;          ;    ;    ;  ;        ; ;               ;       ;    ;        ; ;         ;
;    ;   ;     ;    ;    ;  ;    ;   ;  ;              ;       ;    ;    ;   ;  ;   ;    ;
;     ;;;    ;;;;;   ;;;;    ;;;;   ;;  ;;;           ;;;    ;;;;;   ;;;;   ;;  ;;; ;;;;;
;
;
;
;

;; -----------------------------------------------------------------------------
;; Movement and Eating

;; -----------------------------------------------------------------------------
;; Eating and Growth

;; Snake [Listof Goo] -> Goo or #f
;; Can the snake eat any of the goos?
;; > (can-eat (snake "right" `(,(posn 3 3))) `(,(goo (posn 3 3) 130)))
;; (goo (posn 3 3) 130)
(define (can-eat snake goos)
  (cond [(empty? goos) #f]
        [else (if (close? (snake-head snake) (first goos))
                  (first goos)
                  (can-eat snake (rest goos)))]))

;; [Listof Goo] Goo -> [Listof Goo]
;; Eat and replenish a goo.
;; > (eat (list (goo (posn 5 5) 5)) (goo (posn 5 5) 5))
;; (list (new-goo))
(define (eat goos goo-to-eat)
  (cons (fresh-goo) (remove goo-to-eat goos)))

;; Seg Goo -> Boolean
;; Is the segment close to the goo?
;; > (close? (posn 1 2) (goo (posn 1 2) 4))
;; #t
(define (close? s g)
  (posn=? s (goo-loc g)))

;; Grow the snake one segment.
;; Snake -> Snake
;; > (grow snake0)
;; (snake "right" `(,(posn 2 1) ,(posn 1 1)))
(define (grow sn)
  (snake (snake-dir sn) (cons (next-head sn) (snake-segs sn))))

;; -----------------------------------------------------------------------------
;; Movement

;; Snake -> Snake
;; Slither the snake forward one segment.
;; > (slither snake0)
;; (snake "right" (posn 2 1))
(define (slither sn)
  (snake (snake-dir sn)
         (cons (next-head sn) (all-but-last (snake-segs sn)))))

;; Snake -> Seg
;; Compute the next head position of the snake.
;; > (next-head snake0)
;; (snake "right" (list (posn 2 1)))
(define (next-head sn)
  (define head (snake-head sn))
  (define dir (snake-dir sn))
  (cond [(string=? dir "up") (posn-move head 0 -1)]
        [(string=? dir "down") (posn-move head 0 1)]
        [(string=? dir "left") (posn-move head -1 0)]
        [(string=? dir "right") (posn-move head 1 0)]))

;; Posn Number Number -> Posn
;; Move the position by dx, dy.
;; > (posn-move (posn 1 1) 2 3)
;; (posn 3 4)
(define (posn-move p dx dy)
  (posn (+ (posn-x p) dx)
        (+ (posn-y p) dy)))

;; (cons X [Listof X]) -> [Listof X]
;; Returns a List that is does not contain the last element of the given list.
;; > (all-but-last '(1 2 3 4))
;; '(1 2 3)
(define (all-but-last segs)
  (cond [(empty? (rest segs)) empty]
        [else (cons (first segs)
                    (all-but-last (rest segs)))]))

;; -----------------------------------------------------------------------------
;; Rotting Goo

;; [Listof Goo] -> [Listof Goo]
;; Renew and rot goos.
(define (age-goo goos)
  (rot (renew goos)))

;; [Listof Goo] -> [Listof Goo]
;; Renew any rotten goos.
(define (renew goos)
  (cond [(empty? goos) empty]
        [(rotten? (first goos))
         (cons (fresh-goo) (renew (rest goos)))]
        [else
         (cons (first goos) (renew (rest goos)))]))

;; [Listof Goo] -> [Listof Goo]
;; Rot all of the goos.
(define (rot goos)
  (cond [(empty? goos) empty]
        [else (cons (decay (first goos))
                    (rot (rest goos)))]))

;; Goo -> Boolean
;; has the goo expired?
;; > (rotten? (goo 1 2) 0)
;; #t
(define (rotten? g)
  (zero? (goo-expire g)))

;; Goo -> Goo
;; decreases the expire field of goo by one
;; > (decay (goo (posn 1 2) 2))
;; (goo (posn 1 2) 1)
(define (decay g)
  (goo (goo-loc g) (sub1 (goo-expire g))))

;; -> Goo
;; Create random goo with fresh expiration.
;; Property: The position of the goo is:
;;  - x in (0,WIDTH),
;;  - y in (0,HEIGHT).
(define (fresh-goo)
  (goo (posn (add1 (random (sub1 SIZE)))
             (add1 (random (sub1 SIZE))))
       EXPIRATION-TIME))

;
;
;
;
;
;   ;;; ;;;;
;    ;   ;
;    ;  ;       ;;;    ;;;   ;;;   ;;;; ;
;    ; ;       ;   ;    ;     ;   ;    ;;
;    ;;;;     ;     ;    ;   ;    ;
;    ;   ;    ;;;;;;;    ;   ;     ;;;;;
;    ;   ;    ;           ; ;           ;
;    ;    ;    ;    ;     ; ;     ;     ;
;   ;;;   ;;    ;;;;       ;      ;;;;;;
;                          ;
;                         ;
;                      ;;;;;
;
;; -----------------------------------------------------------------------------

;; String -> Boolean
;; Is the given value a direction?
;; > (dir? "up")
;; #t
(define (dir? x)
  (or (string=? x "up")
      (string=? x "down")
      (string=? x "left")
      (string=? x "right")))

;; Pit Direction-> Pit
;; Change the direction (if not opposite current snake dir)
;; > (world-change-dir world0 "up")
;; (pit snake1 (list goo0))
(define (world-change-dir w d)
  (define the-snake (pit-snake w))
  (cond [(and (opposite-dir? (snake-dir the-snake) d)
              ;; consists of the head and at least one segment:
              (cons? (rest (snake-segs the-snake))))
         (stop-with w)]
        [else
         (pit (snake-change-dir the-snake d)
              (pit-goos w))]))

;; Direction Direction -> Boolean
;; Are d1 and d2 opposites?
;; > (opposite-dir? "up" "down")
;; #t
(define (opposite-dir? d1 d2)
  (cond [(string=? d1 "up")    (string=? d2 "down")]
        [(string=? d1 "down")  (string=? d2 "up")]
        [(string=? d1 "left")  (string=? d2 "right")]
        [(string=? d1 "right") (string=? d2 "left")]))


;
;
;
;
;                                      ;;
;   ;;;;;;                              ;
;    ;    ;                             ;
;    ;    ;     ;;;     ;; ;;;      ;;; ;     ;;;      ;;  ;;;
;    ;    ;    ;   ;     ;;   ;    ;   ;;    ;   ;      ;;;
;    ;;;;;    ;     ;    ;    ;   ;     ;   ;     ;     ;
;    ;  ;     ;;;;;;;    ;    ;   ;     ;   ;;;;;;;     ;
;    ;   ;    ;          ;    ;   ;     ;   ;           ;
;    ;    ;    ;    ;    ;    ;    ;   ;;    ;    ;     ;
;   ;;;   ;;    ;;;;    ;;;  ;;;    ;;; ;;    ;;;;     ;;;;;
;
;
;
;
;; -----------------------------------------------------------------------------

;; Snake Scene -> Scene
;; Draws the snake onto the scene
;; > (snake+scene snake0 MT-SCENE)
;; (place-image SEG-IMG 8 8 MT-SCENE)
(define (snake+scene snake scene)
  (define snake-body-scene
    (img-list+scene  (snake-body snake) SEG-IMG scene))
  (define dir (snake-dir snake))
  (img+scene (snake-head snake)
             (cond [(string=? "up" dir) HEAD-UP-IMG]
                   [(string=? "down" dir) HEAD-DOWN-IMG]
                   [(string=? "left" dir) HEAD-LEFT-IMG]
                   [(string=? "right" dir) HEAD-RIGHT-IMG])
             snake-body-scene))

;; [Listof Goo] Scene -> Scene
;; draws all of the goo to a scene
;; > (goo-list+scene (list goo0) MT-SCENE)
;; (place-image GOO-IMG 32 32 MT-SCENE)
(define (goo-list+scene goos scene)
  ;; [Listof Goo] -> [Listof Posn]
  ;; gets the posns of all the goo
  ;; > (get-posns-from-goo (list (goo (posn 2 2) 1) (goo (posn 3 3) 1))
  ;; (list (posn 2 2) (posn 3 3))
  (define (get-posns-from-goo goos)
    (cond [(empty? goos) empty]
          [else (cons (goo-loc (first goos))
                      (get-posns-from-goo (rest goos)))]))
  (img-list+scene (get-posns-from-goo goos) GOO-IMG scene))

;; [Listof Posn] Image Scene -> Scene
;; Draws a the image to each posn in the list
;; > (img-list+scene (list (posn 1 1)) GOO-IMG MT-SCENE)
;; (place-image GOO-IMG 8 8
;;              (img-list+scene empty GOO-IMG MT-SCENE))
(define (img-list+scene posns img scene)
  (cond [(empty? posns) scene]
        [else (img+scene (first posns)
                         img
                         (img-list+scene (rest posns) img scene))]))

;; Posn Image Scene -> Scene
;; Draws a the given image onto the scene at the posn.
;; > (img+scene (posn 2 2) GOO-IMG MT-SCENE)
;; (place-image GOO-IMG 32 32 MT-SCENE)
(define (img+scene posn img scene)
  (place-image img
               (* (posn-x posn) SEG-SIZE)
               (* (posn-y posn) SEG-SIZE)
               scene))

;
;
;
;
;                            ;;
;   ;;;;;;;                   ;               ;;;; ;
;    ;    ;                   ;              ;    ;;
;    ;    ;   ;; ;;;      ;;; ;             ;           ;;;;   ;; ;  ;      ;;;
;    ;  ;      ;;   ;    ;   ;;             ;          ;    ;   ;; ;; ;    ;   ;
;    ;;;;      ;    ;   ;     ;             ;               ;   ;  ;  ;   ;     ;
;    ;  ;      ;    ;   ;     ;             ;   ;;;;;  ;;;;;;   ;  ;  ;   ;;;;;;;
;    ;    ;    ;    ;   ;     ;             ;      ;  ;     ;   ;  ;  ;   ;
;    ;    ;    ;    ;    ;   ;;              ;     ;  ;    ;;   ;  ;  ;    ;    ;
;   ;;;;;;;   ;;;  ;;;    ;;; ;;              ;;;;;    ;;;; ;; ;;; ;; ;;    ;;;;
;
;
;
;
;; -----------------------------------------------------------------------------

;; Snake -> Boolean
;; Determine if the snake is colliding with itself.
;; > (self-colliding? (snake "up" (list (posn 1 1) (posn 2 1)
;;                                      (posn 2 2) (posn 1 2)
;;                                      (posn 1 1))))
;; #t
(define (self-colliding? sn)
  (cons? (member (snake-head sn) (snake-body sn))))

;; Snake -> Boolean
;; Determine if the snake is colliding with any of the walls.
;; > (wall-colliding? (snake "up" (list (posn 0 1))))
;; #t
(define (wall-colliding? sn)
  (define x (posn-x (snake-head sn)))
  (define y (posn-y (snake-head sn)))
  (or (= 0 x) (= x SIZE)
      (= 0 y) (= y SIZE)))



;
;
;
;
;
;     ;;;     ;;;  ;;; ;;;   ;;;  ;;;;;;;   ;;;;;     ;;;;;;;     ;;;     ;;;;;;   ;;;   ;;;
;      ;;      ;    ;   ;     ;      ;        ;          ;         ;;      ;    ;   ;     ;
;     ;  ;     ;    ;    ;   ;       ;        ;          ;        ;  ;     ;    ;    ;   ;
;     ;  ;     ;    ;     ; ;        ;        ;          ;        ;  ;     ;    ;     ; ;
;     ;  ;     ;    ;      ;         ;        ;          ;        ;  ;     ;;;;;       ;
;    ;;;;;;    ;    ;     ; ;        ;        ;    ;     ;       ;;;;;;    ;  ;        ;
;    ;    ;    ;    ;    ;   ;       ;        ;    ;     ;       ;    ;    ;   ;       ;
;   ;      ;   ;    ;   ;     ;      ;        ;    ;     ;      ;      ;   ;    ;      ;
;  ;;;    ;;;   ;;;;   ;;;   ;;;  ;;;;;;;   ;;;;;;;;  ;;;;;;;  ;;;    ;;; ;;;   ;;   ;;;;;
;
;
;
;
;; -----------------------------------------------------------------------------
;; Posn Posn -> Boolean
;; Are the two posns are equal?
;; > (posn=? (posn 1 1) (posn 1 1))
;; true
(define (posn=? p1 p2)
  (and (= (posn-x p1) (posn-x p2))
       (= (posn-y p1) (posn-y p2))))

;; Access the head position of the snake.
;; snake-head : Snake -> Seg
;; > (snake-head (snake "right" (list (posn 1 1) (posn 2 1)))
;; (posn 1 1)
(define (snake-head sn)
  (first (snake-segs sn)))

;; Snake -> [Listof Segs]
;; returns the snake's body.
;; That is everyting that isn't the snake's head.
(define (snake-body sn)
  (rest (snake-segs sn)))

;; Snake Direction -> Snake
(define (snake-change-dir sn d)
  (snake d (snake-segs sn)))


;
;
;
;
;
;   ;;;;;;;                        ;
;   ;  ;  ;                        ;
;   ;  ;  ;     ;;;      ;;;; ;  ;;;;;;;     ;;;; ;
;   ;  ;  ;    ;   ;    ;    ;;    ;        ;    ;;
;      ;      ;     ;   ;          ;        ;
;      ;      ;;;;;;;    ;;;;;     ;         ;;;;;
;      ;      ;               ;    ;              ;
;      ;       ;    ;   ;     ;    ;    ;   ;     ;
;    ;;;;;      ;;;;    ;;;;;;      ;;;;    ;;;;;;
;
;
;
;
;; -----------------------------------------------------------------------------

;; Initial Structures

(define goo-list (build-list MAX-GOO (lambda (x) (fresh-goo))))
(define snake0 (snake "right" (list (posn 1 1)))) ;; BUG? << -- moving this define into the test module blows up
(define world0 (pit snake0 goo-list))

(define left-snake0 (snake "left" (list (posn 1 1))))
(define left-world0 (pit left-snake0 goo-list))

;; Test Constants

(define snake1 (snake "left" (list (posn 5 5))))
(define snake2 (snake "up" (list (posn 2 2) (posn 2 3) (posn 2 4))))
(define wall-snake (snake "right" (list (posn 0 1) (posn 1 1))))
(define self-eating-snake (snake "up" (list
                                       (posn 19 3)
                                       (posn 19 4)
                                       (posn 20 4)
                                       (posn 21 4)
                                       (posn 22 4)
                                       (posn 22 3)
                                       (posn 21 3)
                                       (posn 20 3)
                                       (posn 19 3)
                                       (posn 18 3))))
(define goo1 (goo (posn 5 5) 45))
(define goo2 (goo (posn 4 8) 1))
(define goo3 (goo (posn 6 9) 40))
(define goo4 (goo (posn 1 1) 120))
(define goo5 (goo (posn 1 9) 58))
(define goo-list1 (list goo1 goo2 goo3 goo4 goo5))
(define world1 (pit snake1 goo-list1))
(define world2 (pit snake2 goo-list1))

(define right-snake1 (snake "right" (list (posn 5 5))))
(define right-world1 (pit right-snake1 goo-list1))

(module+ test

  (require rackunit rackunit/text-ui)

  ;; test the major basic snake functions
  (check-equal? (pit-snake (next-pit world2))
                (snake "up" (list (posn 2 1) (posn 2 2) (posn 2 3))))
  (check-equal? (pit-snake (next-pit world1))
                (snake "left" (list (posn 4 5) (posn 5 5))))
  (check-true (let ([f (pit-goos (next-pit world1))])
                (= (length f) MAX-GOO)))
  (check-equal? (pit-snake (next-pit (pit snake0 (list (goo (posn SIZE SIZE) 100)))))
                (snake "right" (list (posn 2 1))))
  (check-equal? (pit-snake (next-pit (pit snake0 (list (goo (posn 1 1) 130)))))
                (snake "right" (list (posn 2 1) (posn 1 1))))

  (check-equal? (direct-snake world0 "down")
                (world-change-dir world0 "down"))
  (check-equal? (direct-snake world0 "a")
                world0)

  (check-equal? (render-pit world0)
                (snake+scene snake0
                             (goo-list+scene goo-list MT-SCENE)))
  (check-equal? (render-pit world1)
                (snake+scene snake1 (goo-list+scene goo-list1 MT-SCENE)))
  (check-equal? (render-pit world2)
                (snake+scene snake2 (goo-list+scene goo-list1 MT-SCENE)))

  (check-true (dead? (pit wall-snake '())))
  (check-true (dead? (pit self-eating-snake  '())))
  (check-false (dead? (pit snake1  '())))
  (check-false (dead? (pit snake2  '())))
  (check-false (dead? world0))

  (check-equal? (render-end world1)
                (overlay (text "Game over" 15 "black")
                         (render-pit world1)))
  (check-equal? (render-end world2)
                (overlay (text "Game over" 15 "black")
                         (render-pit world2)))

  ;; Properties
  ;; -----------------------------------------------------------------------------

  ;; Property: each goo in the list has its 'expire' field decremented by 1
  (define (prop:goo-rot-- i)
    (test-begin
     (for ([i (in-range i)])
       (define goos (list-of-n-goo MAX-GOO))
       (define goo-initial-expire (map goo-expire goos))
       (check-equal? (map sub1 goo-initial-expire)
                     (map goo-expire (age-goo goos))))))

  ;; Property: The position of the goo is:
  ;;  - x in (0,WIDTH-SEGS),
  ;;  - y in (0,HEIGHT-SEGS).
  (define (prop:new-goo-range i)
    (test-begin
     (for ([i (in-range i)])
       (define f (fresh-goo))
       (check-true (and (< 0 (posn-x (goo-loc f)) SIZE)
                        (< 0 (posn-y (goo-loc f)) SIZE))))))

  ;; Number -> [Listof Goo]
  ;; creates a list of randomly selected goo that is n long.
  (define (list-of-n-goo n)
    (cond [(zero? n) empty]
          [else (define rand (random 5))
                (cons (list-ref goo-list1 rand) (list-of-n-goo (sub1 n)))]))

  ;; testing pit-snake event handling

  (check-equal? (pit-snake (world-change-dir (pit snake1 "foobar") "down"))
                (snake "down" (list (posn 5 5))))
  (check-equal? (pit-snake (world-change-dir (pit snake2 "left") "left"))
                (snake "left" (list (posn 2 2) (posn 2 3) (posn 2 4))))

  (prop:goo-rot-- 1000)

  (check-equal? (grow snake0)
                (snake "right" (list (posn 2 1) (posn 1 1))))
  (check-equal? (grow snake1)
                (snake "left" (list (posn 4 5) (posn 5 5))))
  (check-equal? (grow snake0)
                (snake "right" (list (posn 2 1)
                                     (posn 1 1))))

  (prop:new-goo-range 1000)

  (check-equal? (can-eat (snake "right" `(,(posn 3 3))) `(,(goo (posn 3 3) 130)))
                (goo (posn 3 3) 130))
  (check-false (can-eat (snake "right" `(,(posn 3 3))) `(,(goo (posn 3 4) 130)
                                                         ,(goo (posn 2 2) 0))))
  (check-equal? (can-eat snake0 (list (goo (posn 1 1) 1)))
                (goo (posn 1 1) 1))
  (check-false (can-eat snake0 (list (goo (posn 2 1) 1))))

  (check-equal? (slither snake0) (snake "right" (list (posn 2 1))))
  (check-equal? (slither (snake "right" (list (posn 4 4)
                                              (posn 4 5)
                                              (posn 4 6))))
                (snake "right" (list (posn 5 4) (posn 4 4) (posn 4 5))))
  (check-equal? (slither snake0)
                (snake "right" (list (posn 2 1))))

  (check-equal? (length (eat (list (goo (posn 1 1) 130)) (goo (posn 1 1) 130)))
                1)
  (check-equal? (grow (snake "left" (list (posn 1 1))))
                (snake "left" (list (posn 0 1) (posn 1 1))))

  (check-equal? (next-head snake0) (posn 2 1))
  (check-equal? (next-head (snake "left" (list (posn 1 1))))
                (posn 0 1))
  (check-equal? (next-head (snake "up" (list (posn 1 1))))
                (posn 1 0))
  (check-equal? (next-head (snake "down" (list (posn 1 1))))
                (posn 1 2))
  (check-equal? (next-head snake0) (posn 2 1))

  (check-equal? (posn-move (posn 1 1) 2 3) (posn 3 4))
  (check-equal? (posn-move (posn 3 4) 6 0) (posn 9 4))
  (check-equal? (posn-move (posn 2 8) 0 5) (posn 2 13))
  (check-equal? (posn-move (posn 2 3) 0 0) (posn 2 3))

  (check-equal? (all-but-last '(1 2 3 4 5 6))
                '(1 2 3 4 5))
  (check-equal? (all-but-last (snake-segs snake2))
                `(,(posn 2 2) ,(posn 2 3)))
  (check-equal? (all-but-last (list 0)) empty)
  (check-equal? (all-but-last (list 0 1 2)) (list 0 1))

  ;; testing snake-key-handling

  (check-true (dir? "up"))
  (check-true (dir? "down"))
  (check-true (dir? "left"))
  (check-true (dir? "right"))
  (check-false (dir? "f"))
  (check-true (dir? "right"))

  (check-equal? (world-change-dir world1 "left") world1)
  (check-equal? (world-change-dir world1 "right") right-world1)
  (check-equal? (world-change-dir world0 "left") left-world0)
  (check-equal? (world-change-dir world0 "right")
                (pit (snake "right" (snake-segs (pit-snake world0)))
                     (pit-goos world0)))
  (check-equal? (world-change-dir world0 "down")
                (pit (snake "down" (snake-segs (pit-snake world0)))
                     (pit-goos world0)))

  (check-true (opposite-dir? "up" "down"))
  (check-true (opposite-dir? "left" "right"))
  (check-true (opposite-dir? "right" "left"))
  (check-true (opposite-dir? "down" "up"))
  (check-false (opposite-dir? "left" "down"))
  (check-false (opposite-dir? "right" "down"))
  (check-false (opposite-dir? "down" "left"))
  (check-false (opposite-dir? "up" "right"))
  (check-true (opposite-dir? "up" "down"))
  (check-true (opposite-dir? "down" "up"))
  (check-false (opposite-dir? "up" "up") false)
  (check-equal? (opposite-dir? "right" "left") true)
  (check-equal? (opposite-dir? "left" "right") true)

  ;; testing snake rendering

  (check-equal? (snake+scene snake1 MT-SCENE)
                (place-image HEAD-LEFT-IMG (* 5 SEG-SIZE)
                             (* 5 SEG-SIZE) MT-SCENE))
  (check-equal? (snake+scene snake2 MT-SCENE)
                (img+scene (posn 2 2) HEAD-UP-IMG
                           (img+scene (posn 2 3) SEG-IMG
                                      (img+scene (posn 2 4) SEG-IMG MT-SCENE))))
  (check-equal? (snake+scene (snake "up" (list (posn 1 1))) MT-SCENE)
                (img+scene (posn 1 1) HEAD-UP-IMG MT-SCENE))

  (check-equal? (goo-list+scene (list goo1) MT-SCENE)
                (place-image GOO-IMG (* 5 SEG-SIZE)
                             (* 5 SEG-SIZE) MT-SCENE))
  (check-equal? (goo-list+scene goo-list1 MT-SCENE)
                (img-list+scene (list (posn 5 5) (posn 4 8) (posn 6 9) (posn 1 1) (posn 1 9))
                                GOO-IMG MT-SCENE))

  (check-equal? (img-list+scene (list (posn 3 3) (posn 4 4)) SEG-IMG MT-SCENE)
                (place-image SEG-IMG (* 3 SEG-SIZE) (* 3 SEG-SIZE)
                             (place-image SEG-IMG (* 4 SEG-SIZE) (* 4 SEG-SIZE) MT-SCENE)))
  (check-equal? (img-list+scene (list (posn 1 1) (posn 10 10)) SEG-IMG MT-SCENE)
                (place-image SEG-IMG (* 1 SEG-SIZE) (* 1 SEG-SIZE)
                             (place-image SEG-IMG (* 10 SEG-SIZE) (* 10 SEG-SIZE) MT-SCENE)))
  (check-equal? (img-list+scene (list (posn 1 1)) GOO-IMG MT-SCENE)
                (place-image GOO-IMG SEG-SIZE SEG-SIZE
                             (img-list+scene empty GOO-IMG MT-SCENE)))

  (check-equal? (img+scene (posn 4 3) SEG-IMG MT-SCENE)
                (place-image SEG-IMG (* 4 SEG-SIZE) (* 3 SEG-SIZE)  MT-SCENE))
  (check-equal? (img+scene (posn 5 2) GOO-IMG MT-SCENE)
                (place-image GOO-IMG (* 5 SEG-SIZE) (* 2 SEG-SIZE)  MT-SCENE))
  (check-equal? (img+scene (posn 1 1) SEG-IMG MT-SCENE)
                (place-image SEG-IMG SEG-SIZE SEG-SIZE MT-SCENE))

  ;; testing the endgame
  (check-false (self-colliding? snake1))
  (check-false (self-colliding? snake2))
  (check-false (self-colliding? wall-snake))
  (check-true (self-colliding? self-eating-snake))
  (check-false (self-colliding? snake0))
  (check-true (self-colliding? (snake (snake-dir snake0)
                                      (cons (posn 1 1)
                                            (snake-segs snake0)))))

  (check-false (wall-colliding? snake1))
  (check-false (wall-colliding? snake2))
  (check-false (wall-colliding? self-eating-snake))
  (check-true (wall-colliding? wall-snake))
  (check-true
   (wall-colliding? (snake "right" (list (posn (/ WIDTH-PX SEG-SIZE) 0)))))
  (check-true
   (wall-colliding? (snake "down" (list (posn 0 (/ HEIGHT-PX SEG-SIZE))))))
  (check-true
   (wall-colliding? (snake "up" (list (posn 1 0)))))
  (check-equal? (wall-colliding? (snake "right"
                                        (list (posn 0 1))))
                true)
  (check-equal? (wall-colliding? (snake "right"
                                        (list (posn 1 0))))
                true)
  (check-equal? (wall-colliding? (snake "right"
                                        (list (posn 1 1))))
                false)
  (check-true (wall-colliding? (snake "right" (list (posn 1 SIZE)))))


  ;; testing utilities functions

  (check-false (posn=? (posn 1 1) (posn 2 2)))
  (check-false (posn=? (posn 1 2) (posn 2 1)))
  (check-true (posn=? (posn 3 4) (posn 3 4)))
  (check-true (posn=? (posn 2 2) (posn 2 2)))
  (check-equal? (posn=? (posn 1 2) (posn 1 1)) false)
  (check-equal? (posn=? (posn 1 2) (posn 1 2)) true)
  (check-equal? (posn-move (posn 0 0) 2 3) (posn 2 3))

  (check-equal? (snake-head snake1) (posn 5 5))
  (check-equal? (snake-head snake2) (posn 2 2))
  (check-equal? (snake-head snake0) (posn 1 1))

  (check-equal? (snake-body snake1) empty)
  (check-equal? (snake-body snake0) empty)
  (check-equal? (snake-body snake2) (list (posn 2 3) (posn 2 4)))

  (check-equal? (snake-change-dir snake0 "up")
                (snake "up" (list (posn 1 1))))
  (check-equal? (snake-change-dir snake1 "down")
                (snake "down" (list (posn 5 5))))
  (check-equal? (snake-change-dir snake2 "left")
                (snake "left" (list (posn 2 2) (posn 2 3) (posn 2 4))))

  (check-true (rotten? (goo (posn 1 2) 0)))
  (check-true (rotten? (goo (posn 6 9) 0)))
  (check-true (rotten? (goo (posn 23 2) 0)))

  (check-false (rotten? (goo (posn 1 2) 2)))
  (check-false (rotten? (goo (posn 3 45) 45334534)))
  (check-false (rotten? (goo (posn 2 4) 9)))

  (check-equal? (decay (goo (posn 1 2) 2))
                (goo (posn 1 2) 1))
  (check-equal? (decay (goo (posn 132 0) 2))
                (goo (posn 132 0) 1))
  (check-equal? (decay (goo (posn 1 2) 10))
                (goo (posn 1 2) 9))
  (check-equal? (decay (goo (posn 3 5) 8))
                (goo (posn 3 5) 7))

  "all tests run")

A EjemplosRacket/SICP/Capitulo1/.auctex-auto/Capitulo1.el => EjemplosRacket/SICP/Capitulo1/.auctex-auto/Capitulo1.el +41 -0
@@ 0,0 1,41 @@
(TeX-add-style-hook
 "Capitulo1"
 (lambda ()
   (TeX-add-to-alist 'LaTeX-provided-class-options
                     '(("article" "11pt")))
   (TeX-add-to-alist 'LaTeX-provided-package-options
                     '(("inputenc" "utf8") ("fontenc" "T1") ("ulem" "normalem")))
   (add-to-list 'LaTeX-verbatim-macros-with-braces-local "href")
   (add-to-list 'LaTeX-verbatim-macros-with-braces-local "hyperref")
   (add-to-list 'LaTeX-verbatim-macros-with-braces-local "hyperimage")
   (add-to-list 'LaTeX-verbatim-macros-with-braces-local "hyperbaseurl")
   (add-to-list 'LaTeX-verbatim-macros-with-braces-local "nolinkurl")
   (add-to-list 'LaTeX-verbatim-macros-with-braces-local "url")
   (add-to-list 'LaTeX-verbatim-macros-with-braces-local "path")
   (add-to-list 'LaTeX-verbatim-macros-with-delims-local "path")
   (TeX-run-style-hooks
    "latex2e"
    "article"
    "art11"
    "inputenc"
    "fontenc"
    "graphicx"
    "longtable"
    "wrapfig"
    "rotating"
    "ulem"
    "amsmath"
    "amssymb"
    "capt-of"
    "hyperref")
   (LaTeX-add-labels
    "sec:org4c82b8d"
    "sec:org3c76fd6"
    "sec:orgb15cd54"
    "sec:org29991fc"
    "sec:org9b56e2a"
    "sec:org27f2481"
    "sec:orgf5e0361"
    "sec:orgc1d028d"))
 :latex)


M EjemplosRacket/SICP/Capitulo1/Capitulo1.org => EjemplosRacket/SICP/Capitulo1/Capitulo1.org +3 -2
@@ 1,14 1,15 @@
#+TITLE: Capítulo 1
#+AUTHOR: Camilo Meza Gaete
#+OPTIONS: toc:nil num:nil

* Definiciones

Las expresiones primitivas en el caso de LISP corresponden a átomos (que
representan los símbolos), listas (que contienen los símbolos), y la
función λ (que es el constructor mímino de esos símbolos).
función \(\lambda\) (que es el constructor mímino de esos símbolos).

Contiene definiciones de operaciones aritméticas, definición de
procedimientos desde λ, números decimales, enteros, racionales y
procedimientos desde \(\lambda\), números decimales, enteros, racionales y
símbolos de caracteres.

Un ejemplo de combinación de estos componentes primitivos:

A EjemplosRacket/SICP/Capitulo1/Capitulo1.tex => EjemplosRacket/SICP/Capitulo1/Capitulo1.tex +348 -0
@@ 0,0 1,348 @@
% Created 2022-06-16 Thu 09:25
% Intended LaTeX compiler: pdflatex
\documentclass[11pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{graphicx}
\usepackage{longtable}
\usepackage{wrapfig}
\usepackage{rotating}
\usepackage[normalem]{ulem}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{capt-of}
\usepackage{hyperref}
\author{Camilo Meza Gaete}
\date{\today}
\title{Capítulo 1}
\hypersetup{
 pdfauthor={Camilo Meza Gaete},
 pdftitle={Capítulo 1},
 pdfkeywords={},
 pdfsubject={},
 pdfcreator={Emacs 27.2 (Org mode 9.6)}, 
 pdflang={English}}
\begin{document}

\maketitle

\section*{Definiciones}
\label{sec:org0e88ee1}

Las expresiones primitivas en el caso de LISP corresponden a átomos (que
representan los símbolos), listas (que contienen los símbolos), y la
función \(\lambda\) (que es el constructor mímino de esos símbolos).

Contiene definiciones de operaciones aritméticas, definición de
procedimientos desde \(\lambda\), números decimales, enteros, racionales y
símbolos de caracteres.

Un ejemplo de combinación de estos componentes primitivos:

\begin{verbatim}
(+ 148 998)
\end{verbatim}

La parte de la izquierda de la combinación es llamada operador, y hacia la
derecha se dejan los operandos. de esta manera las combinaciones pueden tener
distinta cantidad de argumentos y operandos según requiera la complejidad de
la abstracción.

\section*{Complicando las expresiones}
\label{sec:org3367b46}

Las combinaciones se pueden anidar y complicar tanto como sea necesario, dando
origen a esto:

\begin{verbatim}
(+ (* 3 (+ (* 2 4) (+ 3 5))) (+ (- 10 7) 6))
\end{verbatim}

Que humanamente es algo más confuso, y para facilitar su lectura, se
utiliza \emph{pretty-printing}:

\begin{verbatim}
(+ (* 3
      (+ (* 2 4)
         (+ 3 5)))
   (+ (- 10 7)
      6))
\end{verbatim}

El intérprete es indiferente a estos cambios en el formato, son sólo para
ayudar a las personas que leen el código fuente en que estas convenciones se
implementan.

Cuando recibe una combinación, el intérprete seguirá su ciclo:
\begin{itemize}
\item Leerá la combinación desde los paréntesis más internos a los más externos.
\item Evaluará todas las expresiones siguiendo el mismo orden.
\item Imprimirá una respuesta a la interfaz, realizando el cálculo de ser
necesario.
\end{itemize}

A este ciclo se lo conoce por sus siglas en inglés \textbf{REPL} (Read-Evaluate-Print Loop).

\section*{Nombrando elementos}
\label{sec:org072f65c}

Consiste en asociar un átomo a otro por medio de una expresión, se denomina
\textbf{variable} a aquello que queremos nombrar y \textbf{valor} al objeto asignado.

\begin{verbatim}
(define radio 5)
radio
\end{verbatim}

Un ejemplo de uso de definiciones para determinar el área de una
circunferencia:

\begin{verbatim}
(define pi 3.14159)
(define radio 10)
(define area (* pi (* radio radio)))
area
\end{verbatim}

Gracias al primitivo \textbf{define} podemos abstraer relaciones cada vez más complejas
entre entidades en LISP.

\section*{Evaluación y combinación}
\label{sec:orga03e463}

Como ya se dijo, el intérprete evalúa desde la parte más interior de las
combinaciones y siguiendo la estructura de evaluar el procedimiento de la
izquierda y aplicando los argumentos hacia la derecha.

\begin{verbatim}
(* (+ 2 (* 4 6))
   (+ 5 3 5))
\end{verbatim}

En el ejemplo de arriba, primero el producto entre 4 y 6, luego las adiciones, y
finalmente el producto entre 26 y 13.

Esta regla general se llama \emph{aplicación} y se lleva a cabo en general; la única
salvedad son las \textbf{formas especiales} (por ejemplo: la función \emph{define}). Estas
formas especiales tienen sus propias reglas de aplicación, lo que permite tener
una sintaxis más simple en general y pequeños añadidos que permiten la
flexibilidad de LISP.

\section*{Procedimientos compuestos}
\label{sec:org5c8ed4d}
Con estos conjuntos de ideas y posibilidades, llegamos al punto en que se logran
definir procedimientos.

Si pensamos en la instrucción general para determinar el cuadrado de un
determinado número, se debe multiplicar el número por sí mismo. En LISP eso se
expresa de la siguiente manera:

\begin{verbatim}
(define (cuadrado x)
  (* x x))
\end{verbatim}

Primero se utiliza la forma especial \textbf{define}, luego se diseña la estructura de
nuestra función con (\emph{nombre} \emph{argumentos}) y posteriormente un \emph{cuerpo}. Donde
nombre es un símbolo que nos permite llamar al procedimiento, los argumentos son
aquellos símbolos que acepta, y el cuerpo aquello que nuestro procedimiento hará
con sus argumentos.

Ahora lo podemos evaluar en un número natural conocido, de manera que se
corrobore que el procedimiento hace aquello para lo que se diseñó.

\begin{verbatim}
(define (cuadrado x)
  (* x x))
(cuadrado 6)
\end{verbatim}

Como ya tenemos un procedimiento definido, lo podemos incluir en la definición
de uno nuevo, por ejemplo la suma de cuadrados \(X^{2}+Y^{2}\).

\begin{verbatim}
(define (cuadrado x)
  (* x x))
(define (suma-de-cuadrados x y)
  (+ (cuadrado x) (cuadrado y)))
(suma-de-cuadrados 3 4)
\end{verbatim}

Y realizar un procedimiento complejo tal que:
\begin{verbatim}
(define (cuadrado x)
  (* x x))
(define (suma-de-cuadrados x y)
  (+ (cuadrado x) (cuadrado y)))
(define (f a)
  (suma-de-cuadrados (+ a 3) (* a 4)))
(f 5)
\end{verbatim}

\begin{verbatim}
464
\end{verbatim}


Entonces, los procedimientos en conjunto se terminan comportando igual que los
primitivos (podemos combinarlos y anidarlos sin un límite), gracias a nuestras
reglas de evaluación.

\section*{Modelo de sustitución}
\label{sec:orgb6b8507}
Imaginemos la secuencia de sustitución que realiza nuestro REPL de acuerdo a la
\hyperref[procedimiento-compuesto]{definición de este código}:

Cuando se invoca la combinación \textbf{(f 5)}, lo primero que se busca es la
definición del símbolo f en el entorno.

En nuestro ejemplo, \textbf{``f''} es un procedimiento que toma como argumento \textbf{``a''}, y
cuyo cuerpo es \emph{``(suma-de-cuadrados (+ a 3) (* a 4))''}.

Se reemplaza el parámetro \textbf{``a''} con el valor entregado al procedimiento f,
quedando \emph{``(suma-de-cuadrados (+ 5 3) (* 5 4))''}.

Para evaluar nuestro procedimiento llamado \textbf{suma-de-cuadrados} primero debemos
evaluar sus argumentos. La suma (+ 5 3) nos entrega el valor 8 para el argumento
``x'', mientras que el producto (* 5 4) nos entrega el valor 20 para el argumento
``y''.

Finalmente, debemos aplicar la definición de \textbf{suma-de-cuadrados} que se reduce a
la evaluación de una combinación con dos operandos y un operador. En esa
situación nos encontramos los siguientes problemas: Debemos evaluar el operador
para obtener el procedimiento que se aplicará, y debemos evaluar los operandos
para obtener los argumentos.

El proceso que se ha descrito se conoce como el \emph{modelo de sustitución} para la
aplicación de procedimientos. Si bien este modelo nos permite conocer el
\textbf{significado} de la aplicación de procedimientos, se deben destacar dos puntos:

\begin{itemize}
\item Esto es sólo un ejemplo para abstraer el modo en que funciona la aplicación de
procedimientos, no para explicar el funcionamiento del intérprete. Ya que la
sustitución que se realiza es más bien el reemplazo de los argumentos por los
parámetros formales del entorno local.
\item Los modelos que se están presentando necesitarán cubrir una mayor complejidad,
por que se deberán ir reemplazando a medida que se requiera.
\end{itemize}

\section*{Orden aplicativo u orden normal}
\label{sec:org4b56fae}
De acuerdo al orden de evaluación que se presentó en la sección \hyperref[sec:orga03e463]{Evaluación y combinación}, el intérprete evalúa primero el operador y los operandos para luego
aplicar el procedimiento a los argumentos resultantes. Aunque esta \emph{no} es la
única forma de realizar una evaluación.

Un modelo alternativo de evaluación puede ser no evaluar los operandos \textbf{hasta}
que se necesiten sus valores. En este caso se sustituyen las expresiones de
operandos por parámetros hasta tener una expresión compuesta exclusivamente de
operadores primitivos.

Por ejemplo, al evaluar \textbf{(f 5)} tendríamos la siguiente expansión:

\begin{verbatim}
(suma-de-cuadrados (+ 5 3) (* 5 4))

(+   (cuadrado (+ 5 3))    (cuadrado (* 5 4))   )

(+   (* (+ 5 3)  (+ 5 3))  (* (* 5 4)  (* 5 4)) )
\end{verbatim}

Seguido de las reducciones:

\begin{verbatim}
(+   (* 8 8)               (* 20 20)             )

(+   64                    400                   )

464
\end{verbatim}

Nos entrega el mismo resultado, siguiendo un procedimiento diferente. En
particular la evaluación de los operandos ``x'' e ``y'' se realiza dos veces,
correspondiente a la expresión \texttt{(* x x)} en la definición de la función
\texttt{(cuadrado x)}.

El método de orden de evaluación en que primero se expande la definición y luego
se evalúa se llama \textbf{orden normal}, en contraste con el orden en que se evalúan
los argumentos y después se aplica que se llama \textbf{orden aplicativo}.

LISP usa evaluación de orden aplicativo pues así ahorra estar evaluando más de
una vez la misma expresión, lo que le permite obtener algo de eficiencia en
estos procedimientos. Además, la evaluación de orden normal se vuelve mucho más
compleja de trabajar cuando se deja de usar el modelo de sustitución.

\section*{Expresiones condicionales y predicados}
\label{sec:org60759cd}
Sin embargo hasta ahora no tenemos una forma de evaluar expresiones más
complejas como, por ejemplo, el valor absoluto de un número. Esto está definido
matemáticamente de la siguiente manera:

\[|x| \begin{cases} x ,&\text{si } x>0 \\ 0 ,&\text{si } x=0 \\ -x ,&
\text{si } x<0\end{cases}\]

El análisis de estos casos se puede dar a través de una forma especial en LISP
asociada a la función \texttt{cond} (que viene de \emph{condicional}). Y aplicando el
ejemplo, sería así:

\begin{verbatim}
(define (abs x)
  (cond ((> x 0) x)
        ((= x 0) 0)
        ((< x 0) (- x))))
(abs -10)
\end{verbatim}

\begin{verbatim}
10
\end{verbatim}


Así, tenemos expresiones condicionales que siguen el patrón detallado a
continuación:

\[(cond (\langle p_{n} \rangle \langle e_{n} \rangle))\]

Donde el símbolo \emph{cond} invoca a la función que evaluará las cláusulas que le
siguen; dichas cláusulas están compuestas por un \emph{predicado}, simbolizado por
\(p_{n}\) en el patrón anterior. El valor del predicado es booleano: sólo puede
ser interpretado como \texttt{verdadero} o \texttt{falso} (en scheme, estos valores se
representan con las constantes \#t o \#f respectivamente).

El proceso de evaluación es el siguiente: Se evaluará el primer predicado, si
éste es \#f entonces se continuará con el que le sucede hasta que se encuentra un
predicado cuyo valor es \#t. En este momento, el intérprete devolverá el valor de
la expresión consecuente \(e_{n}\) que corresponda. De no haber predicados que
cumplan con la condición de ser \#t entonces la condición \emph{cond} quedará
indefinida.

Una forma alternativa de definir valor absoluto sería:

\begin{verbatim}
(define (abs x)
  (cond ((< x 0) (- x))
        (else x)))

(abs -45)
\end{verbatim}

Que equivaldría a la expresión ``Si X es menor que 0, devuelve el inverso aditivo
de X; de otro modo, devuelve X''. En este caso, \texttt{else} es un símbolo especial que
se puede usar para omitir el predicado de una condición, se considera siempre \#t
por lo que devolverá el valor de la expresión consecuente que le suceda.

Existe una tercera forma de escribir la definición de valor absoluto:

\begin{verbatim}
(define (abs x)
  (if (< x 0)
      (- x)
      x))

(abs -3)
\end{verbatim}

Donde if es un símbolo que llama a una función restringida de \emph{cond} donde sólo
hay un predicado con su respectiva expresión consecuente y luego está la
expresión consecuente de un \texttt{else}. Este condicional es útil cuando hay sólo dos
casos en el análisis que evaluar.
\end{document}

A LaTeX/Evaluaciones/InfoGeneral.tex => LaTeX/Evaluaciones/InfoGeneral.tex +35 -0
@@ 0,0 1,35 @@
%=========================================================
%------------ Encabezado ---------------------------------
%=========================================================
\pagestyle{headandfoot}%{head}%empty
\firstpageheader{}{}{}
\runningheader{\disciplina}{}{\evaluacion}
\runningheadrule
\firstpagefooter{\copyright Camilo Meza}{}{Página \thepage\ de \numpages}
\runningfooter{\iflastpage{Otras plantillas en \href{https://}{Repositorio}}{\copyright Camilo Meza}}{}{Página \thepage\ de \numpages}
\runningfootrule

% ===============================================================
%----- Información sobre la evaluación -------------------------
\nombreColegio{Colegio Universal San Francisco de Asís}
\logoInst{\includegraphics[scale=0.17]{Figs/ifbajequie.jpg}}
\Campus{Talagante} % Si no se ocupa, se puede comentar.
\nombreCurso{Nombre del curso} % Si no se ocupa, se puede comentar.
\nomeDisciplina{nome da disciplina}
\DatosPrueba{}
\TerminoPrueba{}
\Semestre{}
\nombreProfesor{Nombre del profesor}
\Alumno{}
\matriculaAlumno{}
% Si no se quiere una imagen de fondo, comentar la línea de abajo.
\imagenFondo{\includegraphics[height=\paperheight]{Figs/Fundo/aranha2.jpeg}}

% ===============================================================
%Instrucciones para la evaluación, dejar en blanco si no se quiere colocar.
\instUno{Su evaluación consta de \numquestions \ preguntas,\ \numpoints \ sumando \  puntos. \textbf{Se permite el uso de calculadora.}}
\instDos{\textbf{El uso de teléfono celular durante la evaluación se interpreta como copia independiente de su uso, por lo que se retira la evaluación y se revisa hasta ese momento.}}
\instTres{\textbf{Respuestas sin justificación o que no incluya los cálculos necesarios no recibirán el puntaje.}}
\instCuatro{Si tiene dudas, levante la mano o realice la pregunta en voz alta.}
\instCinco{}
\instSeis{}