;=====
; CS 111 - Week 6 Lecture 1 - 2026-09-29

(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

empty

(cons 13 empty)

(cons "moo" (cons 13 empty))

;=====
; signature: cons: Anything list -> list
; purpose: expects any expression and a list,
;   and returns a new list with that expression's value
;   as its first element, and everything else in the given
;   list as the rest of the list

(define LIST-O-STUFF
    (cons "Zeke" (cons "moooooo" (cons "baaaaaa"
          (cons 7568429 (cons (circle 40 "solid" "purple") empty))))))

LIST-O-STUFF

(cons "--->" LIST-O-STUFF)

;=====
; DATA DEFINITION
; a NonEmptyList is one of:
;    * (cons Anything empty)
;    * (cons Anything NonEmptyList)

;=====
; signature: first: NonEmptyList -> Anything
; purpose: expects a non-empty list, and returns the
;     first item in that non-empty list

(first LIST-O-STUFF)

;=====
; signature: rest: NonEmptyList -> list
; purpose: expects a non-empty list, and returns the list
;    containing everything except the first element of the
;    given list (get it? it returns the REST of the given list)
;****************************************
; remember: rest ALWAYS returns a list!!
;*****************************************

(rest LIST-O-STUFF)

;=====
; signature: empty?: Anything -> boolean
; purpose: expects any expression with a value, and returns
;     whether it is an empty list

(empty? "moo")
(empty? LIST-O-STUFF)
(empty? empty)

;=====
; signature: list?: Anything -> boolean
; purpose: expects any expression with a value, and returns
;     whether it is of data type list

(list? LIST-O-STUFF)
(list? empty)
(list? "baaaaaaa")

;=====
; signature: length: list -> number
; purpose: expects any list, and returns the number of
;    (top-level) elements in that list
;
; NOTE: in the list data definition, empty ends a list --
;     it is used to "mark" the end of a list, if you will;
;     the empty ending a list is NOT considered to be an element of
;     that list!

(length empty)
(length (cons 13 empty))
(length LIST-O-STUFF)

(list 1 "moo" 2 "oink" 3 (square 25 "solid" "chartreuse"))

;=====
; STARTING a template for "walking through" a list

; well, based on its data definition, a list can be
;    empty, or built using cons --
;    so, a cond expression with at least two branches
;    will frequently be useful for a function involving
;    a non-fixed-size list:

;=====
; NOT YET A COMPLETE TEMPLATE!!!!!!!:
;
; (cond
;     [... ...]
;     [... ...]
;  )

;-----
; and we frequently will first want to ask
;     if the given list we want to "walkk" through is empty
; and, if it ISN'T, you know it is NOT empty,
;     so should be safe to use first, last with it
;
;     and in that case, may want to do SOMETHING
;     *combining*
;         something you do with or based on the FIRST list item
;         to something you do with or based on the REST of the list

;=====
; NOT YET A COMPLETE TEMPLATE!!!!!!!:
;
; (define (a-list-funct a-list)
;    (cond
;        [(empty? a-list) ...]
;        [else
;            (... (first a-list) ...
;                 (rest a-list) ...)]
;    )
; )

;=====
; to help in completing this template...
;
; say I wanted to make my own version of a length function;
;
; say I wanted to name it len

;=====
; signature: len: list -> number
; purpose: expects a list, and returns the number
;    of (top-level) elements in that list

;-----
; need at least one test for each bullet in
;    list's data definition
;    (and more are fine!)

(check-expect (len empty) 0)
(check-expect (len LIST-O-STUFF) 5)

(define (len a-list)
    (cond
        [(empty? a-list) 0]

        ; when a-list is NOT empty, add 1 (for the 1st element)
        ;     to the length of the *rest* of a-list
        
        [else
            (+ 1 
               (len (rest a-list)))]
    )
)

(len empty)
(len LIST-O-STUFF)

;=====
; so - to FINISH this template for a function 
;     "walking through" a list,
;     I want to ADD a CAREFUL call to the function
;     itself...

;=====
; COMPLETED template for a function "walking through" a list
;
; (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
;
;-----
; Do you see how this is the case with len? and with the
; template for a function "walking through" a list?
;
; *   each call to rest REMOVES one list item --
;
; *   if you keeps removing list items, you HAVE to eventually
;     reach the empty list!

;=====
; Another example of a function that "walks through" a list --
;     I want a function add1-list that adds one to each item in
;     a list of numbers

;=====
; signature: add1-list: list -> list
; purpose: expects a list of numbers and returns
;    another list of numbers as a result of adding 1
;    to each number on the given list

(check-expect (add1-list empty)
              empty)

(check-expect (add1-list (list 1 2 3))
              (list 2 3 4))

(define (add1-list num-list)
    (cond
        ; there are no numbers in an empty list - so if num-list
        ;     is empty, just return an empty list

        [(empty? num-list) empty]

        ; but, if num-list is not empty, create a new list
        ;     from the result of cons-ing
        ;         1 + the first element in num-list TO
        ;         the result of calling add1-list on the
        ;             rest of num-list
        
        [else
            (cons (add1 (first num-list))
                  (add1-list (rest num-list)))]
    )
)

(add1-list (list 1 2 3))
(add1-list (list 2 4 6 8 10 12 14 16 18 20))

;=====
; fun fact: DrRacket has a module 2htdp/batch-io

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

(require 2htdp/batch-io)

;-----
; here is an example of one of its functions that reads from
;    a file (the ONLY write function it provides (!!!):

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

;=====
; FUN FACT: you can indicate a newline within a string
;    using the \n character
; (the default display of these in DrRacket's Interactions
;    window is as \n, BUT they WILL appear as newlines when
;    written to a file!)

"====="
"(don't worry, when written to a file the \n characters below"
"    are treated as newlines)"
"====="

"moo\nbaaa\nla la la"

(write-file "sounds.txt" "moo\nbaaa\nla la la")

"====="
"after running this, view the contents of the file sounds.txt"
"====="

;=====
; and here is ONE of SEVERAL functions batch-io provides for READING
;     from a file:

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

(read-words "sounds.txt")

;=====
; hey! since this returns a list, a read-words expression
;     could be an argument to our len function!

(len (read-words "sounds.txt"))