;;; File:
;;;   longest-string.ss
;;; Author:
;;;   Samuel A. Rebelsky
;;; Version: 
;;;   1.0 of October 2002

;;; Procedures:
;;;   longest-string-in-list-1
;;;   longest-string-in-list-2
;;;   longest-string-in-list-3
;;; Parameters:
;;;   los, a list of strings
;;; Purpose:
;;;   Finds one of the longest strings in los.
;;; Produces:
;;;   longest, a list
;;; Preconditions:
;;;   los is a nonempty list.
;;;   every element of los is a string.
;;; Postconditions:
;;;   Does not affect los.
;;;   Returns an element of los.
;;;   No element of los is longer than longest.

;;; Private Procedure:
;;;   longer-string
;;; Parameters:
;;;   left, a string
;;;   right, a string
;;; Purpose:
;;;   Find the longer of left and right.  
;;; Produces:
;;;   longer, a string
;;; Preconditions:
;;;   Both left and right are strings.
;;; Postconditions:
;;;   longer is a string.
;;;   longer is either equal to left or to right.
;;;   longer is at least as long as left.
;;;   longer is at least as long as right.

(display "************************************************************\n")
(display "Version 1: Has the form (lambda (...) (let (...) body))\n")

(define longest-string-in-list-1
  (lambda (los)
    (begin
      (display "Defining longer-string in version 1\n")
      (let ((longer-string
             (lambda (left right)
               (if (<= (string-length right) (string-length left))
                   left
                   right))))
        ; If there is only one string, that string must be the longest.
        (if (null? (cdr los))
            (car los)
            ; Otherwise, take the longer of the first string and the
            ; longest remaining string.
            (longer-string (car los) (longest-string-in-list-1 (cdr los))))))))

(display "Checking the base case, a single-element list.\n")
(display "  (longest-string-in-list-1 (list \"a\"))\n")
(longest-string-in-list-1 (list "a"))
(display "Checking case in which longest string is last.\n")
(display "  (longest-string-in-list-1 
           (list \"alpha\" \"beta\" \"gamma\" \"delta\" \"epsilon\"))\n")
(longest-string-in-list-1 (list "alpha" "beta" "gamma" "delta" "epsilon"))
(display "Checking case in which longest string is first.\n")
(display "  (longest-string-in-list-1 (list \"aaa\" \"aa\" \"a\" \"\"))\n")
(longest-string-in-list-1 (list "aaa" "aa" "a" ""))
(display "Checking case in which all strings are same length.\n")
(display "  (longest-string-in-list-1 (list \"a\" \"b\" \"c\"))\n")
(longest-string-in-list-1 (list "a" "b" "c"))

(display "************************************************************\n")
(display "Version 2: Has the form (let (...) (lambda (...) body))\n")

(display "************************************************************\n")
(display 
 "Version 3: Has the form (lambda (let (...) (if ... (let (...) rest))))\n")

(define longest-string-in-list-3
  (lambda (los)
    ; If there is only one string, that string must be the longest.
    (if (null? (cdr los))
        (car los)
        ; Otherwise, take the longer of the first string and the
        ; longest remaining string.
        (begin
          (display "Defining longer-string in version 3\n")
          (let ((longer-string
                 (lambda (left right)
                   (if (<= (string-length right) (string-length left))
                        left
                        right))))
                (longer-string (car los) 
                               (longest-string-in-list-3 (cdr los))))))))

