Please send questions to st10@humboldt.edu .

(require 2htdp/image)
(require 2htdp/universe)

; CS 131 - Week 5, Lecture 2
; intro to lists, continued!

;------------
; data definition for a list:

; a list is:
;   - empty, OR
;   - (cons anything list)

;------------
; template for a function uses-list that has a list
;    parameter a-list
;
; (define (uses-list ... a-list ...)
;    (cond
;       [(empty? a-list) ...]
;       [else (...(first a-list) ...
;                 (uses-list ... (rest a-list) ...) ...)]
;    )
; )

;----------
; signature: len: list -> number
; purpose: expects a list, and produces the number of
;    top-level elements in the list

; better have at least 2 check-expects -- one for the
;    empty list case, and one for the non-empty-list
;    case!

(check-expect (len empty) 0)
(check-expect (len (cons 1 (cons "dog" (cons true empty))))
              3)

(define (len a-list)
   (cond
      [(empty? a-list) 0]
      [else (+ 1 (len (rest a-list)))]
   )
)

(len (cons 1 (cons 23 (cons 15 (cons 4 empty)))))  

;----------
; this function is so useful, it is built in, under the
;    name length

(length (cons 1 (cons 2 (cons 350 empty))))

;-------------
; I decide I want a function that expects a list of
;    numbers, and produces a new version of that
;    list where each number is 1 bigger than before

; problem analysis and data definition step:
; ...gee, this is a specialized list!

; SO: here's a data definition for that specialized list!

;-----------
; data definition for a number-list
; 
; a number-list is:
;   - empty, or
;   - (cons number number-list)

;------------
; template for a function uses-num-list that has a number-list
;    parameter num-list
;
; (define (uses-num-list ... num-list ...)
;    (cond
;       [(empty? num-list) ...]
;       [else (...(first num-list) ...
;                 (uses-num-list ... (rest num-list) ...) ...)]
;    )
; )

; now ready for next design recipe step, signature/purpose/header
;    (remember: THEN developed check-expects,
;               THEN pasted in the above template into the
;                    function body and modified it into
;                    what you see below;
;               you are just seeing the FINISHED version here;)

;-----------
; signature: add1map: number-list -> number-list
; purpose: expects a list of numbers and produces a
;    new list of numbers where every number is 1
;    more than in the given list

(define (add1map num-list)
   (cond
      [(empty? num-list) empty]
      [else (cons (+ 1 (first num-list))
                  (add1map (rest num-list)))]
   )
)

(check-expect (add1map empty) empty)
(check-expect (add1map (cons 2 (cons 17 (cons 4 empty))))
              (cons 3 (cons 18 (cons 5 empty))))
(add1map (cons 2 (cons 17 (cons 4 empty))))

;----------
; I'd like a function that expects a list of circle radii
;    and produces a scene containing centered circles
;    with those radii

; (number-list already has a data definition above)

;----------
; signature: many-circles: number-list -> scene
; purpose:  expects a list of circle radii
;    and produces a scene containing centered circles
;    with those radii

; REFACTORED after class to now have use a BACKDROP named 
;    constant, too...

(define WIDTH 300)
(define HEIGHT 200)
(define BACKDROP (empty-scene WIDTH HEIGHT))

; again, remember: we used the design recipe to develop
;    this, including writing the check-expects BEFORE
;    writing the function body, and including pasting
;    in the template for a function expecting a number-list,
;    which we then modified into the function body below

(define (many-circles rad-list)
   (cond
      [(empty? rad-list) BACKDROP]
      [else (place-image 
               (circle (first rad-list) "outline" "black")
               (/ WIDTH 2)
               (/ HEIGHT 2)
               (many-circles (rest rad-list)))]
   )
)

(check-expect (many-circles empty)
              BACKDROP)

(check-expect (many-circles (cons 50 (cons 25 (cons 66 empty))))
              (place-image 
                 (circle 50 "outline" "black")
                 (/ WIDTH 2)
                 (/ HEIGHT 2)
                 (place-image 
                    (circle 25 "outline" "black")
                    (/ WIDTH 2)
                    (/ HEIGHT 2)
                    (place-image
                       (circle 66 "outline" "black")
                       (/ WIDTH 2)
                       (/ HEIGHT 2)
                       BACKDROP))))

(many-circles (cons 50 (cons 25 (cons 66 empty))))

;----------
; I want to try out many-circles with longer radius
;     lists -- but I don't want to type that all out myself...
; I want Racket to generate random radii for me!

; if I want Racket to do something a set number of
;   times, that kind of value is like a whole number
;   (the integers 0, 1, 2, 3, ...)

; a whole-number can be described in a very list-like way!

;----------
; data definition for a whole-number:
;
; a whole-number is:
;    - 0, or
;    - (+ 1 whole-number)

;----------
; template for a function number-funct that has a 
;    whole-number parameter num-times
;    (really, you want this when you want to DO something
;    a certain number of times)

; (define (number-funct ... num-times ...)
;    (cond
;       [(= num-times 0) ...]
;       [else (... num-times ...
;                  (number-funct ... (- num-times 1) ...)
;             ...)]
;    )
; )
;  

; here is a description of the random function you get along
;    with the Beginning Student Level of Racket:

;----------
; signature: random: number -> number
; purpose: expects the ending value in an open
;    interval, and returns a number in the range 
;    [0, that value)

(random 50) ; I'll get values in the interval [0, 50)

;----------
; SO -- with the data definition of whole-number in place,
;    I'll now use it in a function generate-radii...

; I'd like all my radii to be at least 5, and at most (whichever
;    is the smallest of the width and height of the scene) divided
;    by 2 

(define MIN-RAD 5)
(define MAX-RAD (/ (min WIDTH HEIGHT) 2))

;----------
; signature: generate-radii: whole-number -> number-list
; purpose: expects the number of radii desired, and
;    generates a list of that many radii all in the
;    range [MIN-RAD, MAX-RAD)

; and this is the function resulting AFTER following the
;    design recipe steps in order...

(define (generate-radii how-many)
    (cond
       [(= how-many 0) empty]
       [else (cons (+ MIN-RAD (random (- MAX-RAD MIN-RAD)))
                   (generate-radii (- how-many 1)))]
    )
)

(check-expect (generate-radii 0) empty)

;  YES, this next test is a cheesy test! It takes a bit more effort to
;    develop reasonable tests when random is involved...
;    (so you'd BETTER run a few extra examples, and make sure
;    the function behaves as you expect...

; at least this will test if the generated result is a list,
;    and is of length 4...

(check-expect (length (generate-radii 4)) 4)

(generate-radii 10)
(many-circles (generate-radii 10))
(many-circles (generate-radii 100))
(many-circles (generate-radii 25))