#lang racket (require csc151) (provide (all-defined-out)) ;;; File: ;;; analysis-lab.rkt ;;; Authors: ;;; Janet Davis ;;; Titus Klinge ;;; Samuel A. Rebelsky ;;; Jerod Weinman ;;; YOUR NAME HERE ;;; Summary: ;;; Procedures for the lab on analyzing procedures ; +--------------------------------+---------------------------------- ; | Generalized Counter Procedures | ; +--------------------------------+ ;;; Procedure: ;;; counter-new ;;; Parameters: ;;; name, a string ;;; Purpose: ;;; Create a counter associated with the given name. ;;; Produces: ;;; counter, a counter ;;; Preconditions: ;;; [No additional] ;;; Postconditions: ;;; counter can be used as a parameter to the various counter ;;; procedures. ;;; Process: ;;; Counters are two element vectors. Element 0 is the name, and ;;; should not change. Element 1 is the count, and should change. (define counter-new (lambda (name) (vector name 0))) ;;; Procedure: ;;; counter-increment! ;;; Parameters: ;;; counter, a counter ;;; Purpose: ;;; count the counter ;;; Produces: ;;; counter, the same counter, now mutated ;;; Preconditions: ;;; counter was created by counter-new (or something similar) and ;;; has only been modified by the counter procedures. ;;; Postconditions: ;;; (counter-get counter) gives a number one higher than it ;;; did before. (define counter-increment! (lambda (counter) (vector-set! counter 1 (+ 1 (vector-ref counter 1))) counter)) ;;; Procedure: ;;; counter-get ;;; Parameters: ;;; counter, a counter ;;; Purpose: ;;; Get the number of times that counter-count has been called ;;; on this counter. ;;; Produces: ;;; count, a non-negative integer ;;; Preconditions: ;;; counter was created by counter-new and has only been modified ;;; by the counter procedures. ;;; Postconditions: ;;; count is the number of calls to counter-new on this counter since ;;; the last call to counter-reset! on this counter, or since the ;;; counter was created, if there have been no calls to counter-reset! (define counter-get (lambda (counter) (vector-ref counter 1))) ;;; Procedure: ;;; counter-reset! ;;; Parameters: ;;; counter, a counter ;;; Purpose: ;;; reset the counter ;;; Produces: ;;; counter, the same counter, now set to 0 ;;; Preconditions: ;;; counter was created by counter-new (or something similar) and ;;; has only been modified by the other counter procedures. ;;; Postconditions: ;;; (counter-get counter) gives 0. (define counter-reset! (lambda (counter) (vector-set! counter 1 0) counter)) ;;; Procedure: ;;; counter-print ;;; Parameters: ;;; counter, a counter ;;; Purpose: ;;; Print out the information associated with the counter. ;;; Produces: ;;; counter, the same counter ;;; Preconditions: ;;; counter was created by counter-new and has only been modified ;;; by the various counter procedures. ;;; Postconditions: ;;; counter is unchanged. ;;; The output port now contains information on counter. ;;; Ponderings: ;;; Why does counter-print have a bang, given that it doesn't mutate ;;; it's parameter? Because it mutates the broader environment - we ;;; call counter-print not to compute a value, but to print something. (define counter-print (lambda (counter) (display (vector-ref counter 0)) (display ": ") (display (vector-ref counter 1)) (newline))) ; +-------------------+----------------------------------------------- ; | Specific Counters | ; +-------------------+ (define alphabetically-first-1-counter (counter-new "alphabetically-first-1")) (define alphabetically-first-2-counter (counter-new "alphabetically-first-2")) (define alphabetically-first-counters (list alphabetically-first-1-counter alphabetically-first-2-counter)) ; +--------------------------+---------------------------------------- ; | Finding the first string | ; +--------------------------+ ;;; Procedure: ;;; first-of-two ;;; Parameters: ;;; str1, a string ;;; str2, a string ;;; Purpose: ;;; Find the alphabetically first of two strings. ;;; Produces: ;;; first, a string ;;; Preconditions: ;;; [No additional] ;;; Postconditions: ;;; * first is either str1 or str2 ;;; * (string-ci<= first str1) ;;; * (string-ci<= first str2) (define first-of-two (lambda (str1 str2) (if (string-ci<=? str1 str2) str1 str2))) ;;; Procedure: ;;; alphabetically-first ;;; Parameters: ;;; strings, a list of strings ;;; Purpose: ;;; Finds the alphabetically first string in the list. ;;; Produces: ;;; first, a string ;;; Preconditions: ;;; strings contains at least one element ;;; Postconditions: ;;; * first is an element of strings ;;; * For any string, str, in strings (define alphabetically-first-1 (lambda (strings) (counter-increment! alphabetically-first-1-counter) (cond [(null? (cdr strings)) (car strings)] [(string-ci<=? (car strings) (alphabetically-first-1 (cdr strings))) (car strings)] [else (alphabetically-first-1 (cdr strings))]))) (define alphabetically-first-2 (lambda (strings) (counter-increment! alphabetically-first-2-counter) (if (null? (cdr strings)) (car strings) (first-of-two (car strings) (alphabetically-first-2 (cdr strings)))))) (define alphabetically-first-3 (lambda (strings) (let kernel ([first-so-far (car strings)] [remaining (cdr strings)]) (if (null? remaining) first-so-far (kernel (first-of-two first-so-far (car remaining)) (cdr remaining)))))) (define alphabetically-first-4 (lambda (strings) (when (not (all-string? strings)) (error "alphabetically-first: expects a list strings; received" strings)) (if (null? (cdr strings)) (car strings) (first-of-two (car strings) (alphabetically-first-4 (cdr strings)))))) ;;; Procedure: ;;; all-string? ;;; Parameters: ;;; lst, a list ;;; Purpose: ;;; Determine if all elements of lst are strings. ;;; Produces: ;;; ok?, a Boolean (define all-string? (lambda (lst) (or (null? lst) (and (string? (car lst)) (all-string? (cdr lst)))))) ; +-----------------+------------------------------------------------- ; | List Procedures | ; +-----------------+ ;;; Procedure: ;;; list-append ;;; Parameters: ;;; front, a list of size n ;;; back, a list of size m ;;; Purpose: ;;; Put front and back together into a single list. ;;; Produces: ;;; appended, a list of size n+m. ;;; Preconditions: ;;; front is a list [Unverified] ;;; back is a list [Unverified] ;;; Postconditions: ;;; For all i, 0 <= i < n, ;;; (list-ref appended i) is (list-ref front i) ;;; For all i, n <= i < n+m ;;;; (list-ref appended i) is (list-ref back (- i n)) (define list-append (lambda (front back) (if (null? front) back (cons (car front) (list-append (cdr front) back))))) (define list-reverse-1 (lambda (lst) (if (null? lst) null (list-append (list-reverse-1 (cdr lst)) (list (car lst)))))) (define list-reverse-2 (lambda (lst) (let kernel ([reversed null] [remaining lst]) (if (null? remaining) reversed (kernel (cons (car remaining) reversed) (cdr remaining))))))