;===== ; CS 111 - Week 6 Lecture 2 - 2026-10-01 (require 2htdp/image) (require 2htdp/universe) ;===== ; DATA DEFINITION ; an Anything is an expression of any type ;===== ; DATA DEFINITION ; a list is one of: ; * empty ; * (cons Anything list) ; cons for CONStruct a list ;===== ; COMPLETED template for a function that "walks through" a list ; ; * "walks through"? Might need to do something involving or ; to *each* element in a list of unknown size ; ; * AFTER writing your tests for such a function, ; (being SURE to include at least one test ; with an empty list AND at least one with ; a NON-empty list, and MORE if there are additional ; cases), ; * PASTE this into your function body to help ; in COMPLETING that function body: ; ; (define (a-list-funct ... a-list ...) ; (cond ; [(empty? a-list) ...] ; [else (... ; ... (first a-list) ... ; (a-list-funct ... (rest a-list) ...) ...)] ; ) ; ) ;===== ; NOTE: when a function CALLS itself, ; like len does, and as this template does, ; that function is called a RECURSIVE function ; ; IMPORTANT: a recursive function NEEDS: ; * at least one BASE CASE -- at least one ; branch that does NOT call itself, to serve as ; a base, or ending point, for the repeated calls ; to itself! ; ; * each RECURSIVE CASE -- each branch that DOES call ; itself -- needs to do so on a "smaller" version of ; the given parameter, ; such that, eventually, one of the base cases WILL be ; reached ;===== ; a little more file input/file output ; (file i/o) ; Racket's library for this: batch-io (require 2htdp/batch-io) ;===== ; REMINDER ;----- ; 2htdp/batch-io has a selection of file input and file output functions ; (as would be needed for a so-called batch program, one with ; no interactive input/output, ; that reads its needed input from file(s) and writes its ; resulting output to file(s) ;===== ; REMINDER ;===== ; signature: write-file: string string -> string ; purpose: expects the name of a file written as a string -- ; either its full/"absolute" name OR its name in the current ; working directory -- ; AND the string to write to that file, ; has the SIDE-EFFECT of trying to write that string ; to that file, creating the file if necessary, ; (and OVERWRITING its current contents if it exists), ; and returns the *name* of the file it wrote ;----- ; REMINDER ;----- ; You can use \n to mean the newline character (write-file "demo.txt" "Hello there!\nHow are you?\nI am fine!\n") "=====" " You should now have a file demo.txt containing 3 lines of text." "=====" ;===== ; REMINDER ;===== ; signature: read-words: string -> list ; purpose: expects the name of a file written as a string -- ; either its full/"absolute" name OR its name in the current ; working directory -- ; has the SIDE-EFFECT of trying to open and read the contents of ; that file, ; and returns the contents as a list of strings, with each ; white-space-separated "token"/"word" being a string in this list "=====" "You should see a list of the 'words' in demo.txt" "=====" (read-words "demo.txt") ;===== ; Oh, you wanted a list of the LINES in a file? ;===== ; signature: read-lines: string -> list ; purpose: expects the name of a file written as a string -- ; either its full/"absolute" name OR its name in the current ; working directory -- ; has the SIDE-EFFECT of trying to open and read the contents of ; that file, ; and returns the contents read as a list of strings, ; each line in the file being one string in the result "=====" "You should see a list of the lines in demo.txt" "=====" (read-lines "demo.txt") ;===== ; Oh, you wanted a list containing lists of the "words" ; in each line of a file? ;===== ; signature: read-words/line: string -> list ; purpose: expects the name of a file ; written as a string, ; ; has the SIDE-EFFECT of trying to open ; and read the contents of that file, ; ; and returns its contents as a list of ; lists, one sub-list per line, with ; the white-space-separated ; "words"/chunks in that line as ; strings in that line's list "=====" "You should see a list of 3 lists, each containing the 'words'" " in one of the lines of demo.txt" "=====" (read-words/line "demo.txt") ;===== ; Or, maybe you'd like a file's contents as one single string? ; (with \n for newlines in that file?) ;===== ; signature: read-file: string -> string ; purpose: expects the name of a file ; written as a string, ; ; has the SIDE-EFFECT of trying to ; open that file and read its contents, ; ; then returns the contents read as ; a single string "=====" " You should see ONE string with all of the contents of demo.txt" " (with \n for each newline)" "=====" (read-file "demo.txt") ;===== ; I'd like to have a big-bang world that is ; a list of images... ; ; And: I'd like those images be displayed randomly ; in a scene each time big-bang draws its ; world... ;----- ; some useful named constants (define SC-WIDTH 300) (define SC-HEIGHT 200) (define BACKGRD (empty-scene SC-WIDTH SC-HEIGHT)) ;===== ; IF I don't want just ONE never-changing scene, ; I need EITHER an on-tick clause ; or some OTHER handler clause that DOES change ; the world; ; Here, I'd be happy if the world was UNCHANGED ; each time big-bang's ticker ticks ; (but still prompt big-bang to AGAIN call ; its to-draw function to RE-draw the current ; world value in a scene) ;----- ; I can get this by giving on-tick a function ; that simply returns the current world ; UNCHANGED...!!! ;===== ; signature: return-current: Anything -> Anything ; purpose: expects any expression with a value, ; and returns its value (check-expect (return-current 15) 15) (check-expect (return-current #true) #true) (define (return-current a-val) a-val ) ;===== ; to-draw in this case needs a function that'll ; create a scene from a list of images, ; placing each randomly into a scene ;===== ; signature: draw-images-randomly: list -> scene ; purpose: expects a list of images, and returns a ; scene with those images placed at random ; locations ;----- ; need at least two tests, and for a function expecting ; a list of uncertain size, ; one of those tests needs to be for an empty list! (check-expect (draw-images-randomly empty) BACKGRD) ;----- ; for more-convenient testing... (define SHAPE-TRIO (cons (circle 30 "solid" "purple") (cons (triangle 35 "outline" "darkgreen") (cons (square 50 "solid" "gray") empty)))) SHAPE-TRIO (check-random (draw-images-randomly SHAPE-TRIO) (place-image (first SHAPE-TRIO) (random SC-WIDTH) (random SC-HEIGHT) (place-image (second SHAPE-TRIO) (random SC-WIDTH) (random SC-HEIGHT) (place-image (third SHAPE-TRIO) (random SC-WIDTH) (random SC-HEIGHT) BACKGRD)))) (define (draw-images-randomly image-list) (cond [(empty? image-list) BACKGRD] [else (place-image (first image-list) (random SC-WIDTH) (random SC-HEIGHT) (draw-images-randomly (rest image-list)))] ) ) (draw-images-randomly SHAPE-TRIO) "=====" "non-interactive version -- " " CLOSE the big-bang World window to continue!" "=====" (big-bang SHAPE-TRIO (on-tick return-current 0.5) (to-draw draw-images-randomly)) ;===== ; Another useful kind of thing to do with a list: ; ; a FILTER function - removes data from a set of ; data (based on what you want) ; (get it? filter out what you don't want, ; or, if you prefer, ; filter to keep just what you want...) ;===== ; for example: say you want JUST the strings from ; a list? ;===== ; signature: grab-strings: list -> list ; purpose: expects any list and returns a list of ; JUST the strings from the given list. If the list ; is empty or has no strings, returns the empty list. ;===== ; I'd like at least FOUR tests here... ; * test on an empty list ; * test on a list with NO strings ; * test on a list with a MIX of strings and non-strings ; * test on a list of ALL strings (check-expect (grab-strings empty) empty) (check-expect (grab-strings (list 1 2 3 4)) empty) (check-expect (grab-strings (list "hi" 15 "wow" #true)) (list "hi" "wow")) (check-expect (grab-strings (list "hi" "hey" "bye")) (list "hi" "hey" "bye")) (define (grab-strings a-list) (cond [(empty? a-list) empty] ; if a-list is not empty, does it START with a string? [(string? (first a-list)) (cons (first a-list) (grab-strings (rest a-list)))] ; if reach here, a-list is NOT empty AND does not ; START with a string [else (grab-strings (rest a-list))] ) ) (grab-strings (list "hi" 15 "wow" #true)) ;===== ; STARTED a function for big-bang's on-key clause, ; to allow us to ADD an image to a given list of images based ; on a given keystroke ; HOPE to finish this Tuesday, Week 7 Lecture 1! ;;===== ;; signature: add-shape: list string -> list ;; purpose: expects a list of images and a shape key, ;; either c or t or s, and returns a new list ;; with a new first shape added to the given list ;; as follows: ;; for "c", 20-pixel solid randomly-colored circle ;; for "t", 25-pixel solid randomly-colored triangle ;; for "s", 25-pixel solid randomly-colored star ;; and its nothing if given any other string ; ;; FINISH TUESDAY ; ;(check-random (add-shape SHAPE-TRIO "moo") SHAPE-TRIO) ;(check-random (add-shape empty "c") (list )) ;(check-random (add-shape ) ()) ;(check-random (add-shape ) ()) ; ;(define (add-shape image-list shape-key) ; ... ;) ;