Copyright © 2005 Suradet Jitprapaikulsarn
สงวนลิขสิทธิ์ 2548 สุรเดช จิตประไพกุลศาล

Homework 12 (Due 12 September 2005)

1. Write a data definition of a student records.  Each student record contains the following data

Hint: Use the data definiton of date in the previous exercise.

C Solution.

//--------------------------------------------------------------------------
// Data Definition
// ---------------
// A student record (SR) is a structure consisting of
//      - student id as number
//      - student first name as string
//      - student last name as string
//      - student Phone number as number
//      - student birthday as Date
//--------------------------------------------------------------------------
struct StudentRecord
{
    int             id;
    std::string     firstName;
    std::string     lastName;
    int             Phone;
    Date            birthday;
};

//--------------
// Data Example
//--------------
StudentRecord student_1 = { 123456, "Tom", "Cruise",  345463474, { 10, 9, 1960 } };
StudentRecord student_2 = { 322344, "Brad", "Pitt",   523452345, {  3, 5, 1967 } };
StudentRecord student_3 = { 547824, "Val", "Klimmer", 136564566, { 25, 7, 1965 } };

//--------------
// Code Pattern
//--------------
// ... G(StudentRecord r)
// {
//     ... r.id ...
//     ... r.lastName ...
//     ... r.firstName ...
//     ... r.Phone ...
//     ... F(r.birthday) ...
// }

//--------------------------------------------------------------------------
// Data Definition
// ---------------
// A list of student records is either
//      - an empty list
//  or a structure consisting of
//      - first as StudentRecord
//      - last as ListOfStudentRecord
//--------------------------------------------------------------------------
struct ListOfStudentRecord
{
    StudentRecord           first;
    ListOfStudentRecord     *rest;
};

//--------------
// Data Example
//--------------
ListOfStudentRecord *empty = 0;
ListOfStudentRecord list_1 = { student_1, empty };
ListOfStudentRecord list_2 = { student_2, &list_1 };
ListOfStudentRecord list_3 = { student_3, &list_2 };

//--------------
// Code Pattern
//--------------
// ... H(ListOfStudentRecord * L)
// {
//      if (L == 0)
//      {
//          ...
//      }
//      else
//      {
//          ... G(L->first) ...
//          ... H(L->rest) ...
//      }
// }

Scheme Solution.

;----------------------------------------------------------------------------
; Data Definition
; ---------------
; A student record (SR) is a structure consisting of
;      - student id as number
;      - student first name as string
;      - student last name as string
;      - student Phone number as number
;      - student birthday as Date
;----------------------------------------------------------------------------
(define-struct SR (id firstName lastName phone birthday))

;----------------
; Data Example
;----------------
(define student_1 (make-SR 123456 "Tom" "Cruise" 345463474 (make-date 10 9 1960)))
(define student_2 (make-SR 322344 "Brad" "Pitt" 523452345 (make-date 3 5 1967)))
(define student_3 (make-SR 547824 "Val" "Klimmer" 136564566 (make-date 25 7 1965)))

;----------------
; Code Pattern
;----------------
; (define (G r)
;     ... (SR-id r) ...
;     ... (SR-lastName r) ...
;     ... (SR-firstName r) ...
;     ... (SR-phone r) ...
;     ... (F (SR-birthday r)) ...

;----------------------------------------------------------------------------
; Data Definition
; ---------------
; A list of student records is either
;      - an empty list
;  or a structure consisting of
;      - first as StudentRecord
;      - last as ListOfStudentRecord
;----------------------------------------------------------------------------

;----------------
; Data Example
;----------------
(define list_1 (cons student_1 empty))
(define list_2 (cons student_2 list_1))
(define list_3 (cons student_3 list_2))

;----------------
; Code Pattern
;----------------
;(define (H L)
;  (cond
;    [(empty? L) ...]
;    [else ... (G (first L)) ...
;          ... (H (rest L)) ...]))

2. Write a function, findOldest, to get the student ID of the oldest student in a list of student records.

Hint:     1) Define a list of student records

            2) Wrtie a function to compare date

C Solution.

//--------------------------------------------------------------------------
// @description determine whether the first date is prior to the second date
// @param d1 the first date
// @param d2 the second date
// @contract older : Date Date -> boolean
// @return true if d1 < d2, false otherwise
// @example older(date_1, date_2) == true
// @example older(date_2, date_1) == false
// @example older(date_2, date_3) == true
//--------------------------------------------------------------------------
bool older(Date d1, Date d2)
{
    return (d1.year < d2.year) ||
           (d1.year == d2.year && nDay(d1) < nDay(d2));
}

//--------------------------------------------------------------------------
// @description find the id of the oldest student
// @param L a list of student records
// @param r the record of the oldest student so far
// @return the id of the oldest student
// @contract findOldestHelper : ListOfStudentRecord StudentRecord -> number
// @example findOldestHelper(empty, student_2) == 322344
// @example findOldestHelper(&list_1, student_2) == 123456
// @example findOldestHelper(&list_2, student_2) == 123456
// @example findOldestHelper(&list_3, student_2) == 123456
//--------------------------------------------------------------------------
int findOldestHelper(ListOfStudentRecord * L, StudentRecord r)
{
    if (L == 0)
    {
        return r.id;
    }
    else
    {
        if ( older(r.birthday, L->first.birthday) )
        {
            return findOldestHelper(L->rest, r);
        }
        else
        {
            return findOldestHelper(L->rest, L->first);
        }
    }
}

//--------------------------------------------------------------------------
// @description find the id of the oldest student
// @param L a list of student records
// @return 0 if the list is empty, otherwise the id of the oldest student
// @contract findOldest : ListOfStudentRecord -> number
// @example findOldest(empty) == 0
// @example findOldest(&list_1) == 123456
// @example findOldest(&list_2) == 123456
// @example findOldest(&list_3) == 123456
//--------------------------------------------------------------------------
int findOldest(ListOfStudentRecord * L)
{
    if (L == 0)
    {
        return 0;
    }
    else
    {
        return findOldestHelper(L->rest, L->first);
    }
}

Scheme Solution.

;----------------------------------------------------------------------------
; @description determine whether the first date is prior to the second date
; @param d1 the first date
; @param d2 the second date
; @contract older : Date Date -> boolean
; @return true if d1 < d2, false otherwise
; @example (older date_1 date_2) = true
; @example (older date_2 date_1) = false
; @example (older date_2 date_3) = true
;----------------------------------------------------------------------------
(define (older d1 d2)
  (or (< (date-year d1) (date-year d2))
      (and (= (date-year d1) (date-year d2))
           (< (nDay d1) (nDay d2)))))

;----------------------------------------------------------------------------
; @description find the id of the oldest student
; @param L a list of student records
; @param r the record of the oldest student so far
; @return the id of the oldest student
; @contract findOldestHelper : ListOfStudentRecord StudentRecord -> number
; @example (findOldestHelper empty student_2) = 322344
; @example (findOldestHelper list_1 student_2) = 123456
; @example (findOldestHelper list_2 student_2) = 123456
; @example (findOldestHelper list_3 student_2) = 123456
;----------------------------------------------------------------------------
(define (findOldestHelper L r)
  (cond
    [(empty? L) (SR-id r)]
    [(older (SR-birthday r) (SR-birthday (first L))) (findOldestHelper (rest L) r)]
    [else (findOldestHelper (rest L) (first L))]))

;----------------------------------------------------------------------------
; @description find the id of the oldest student
; @param L a list of student records
; @return 0 if the list is empty, otherwise the id of the oldest student
; @contract findOldest : ListOfStudentRecord -> number
; @example (findOldest empty) = 0
; @example (findOldest list_1) = 123456
; @example (findOldest list_2) = 123456
; @example (findOldest list_3) = 123456
;----------------------------------------------------------------------------
(define (findOldest L)
  (cond
    [(empty? L) 0]
    [else (findOldestHelper (rest L) (first L))]))

3. Write a function, findFirstPhone, to get the last name of the student whose has the smallest phone number from the list of student records.

C Solution.

//--------------------------------------------------------------------------
// @description find the last name of the student with the smallest Phone
//              number
// @param L a list of student records
// @param r a student record with the smallest Phone number so far
// @return "" if L is empty, otherwise, the last name of the student with
//         the smallest Phone number
// @contract findFirstPhoneHelper : ListOfStudentRecord -> string
// @example findFirstPhoneHelper(empty, student_2) == "Pitt"
// @example findFirstPhoneHelper(&list_1, student_2) == "Cruise"
// @example findFirstPhoneHelper(&list_2, student_2) == "Cruise"
// @example findFirstPhoneHelper(&list_3, student_2) == "Klimmer"
//--------------------------------------------------------------------------
std::string findFirstPhoneHelper(ListOfStudentRecord * L, StudentRecord r)
{
    if (L == 0)
    {
        return r.lastName;
    }
    else
    {
        if (L->first.Phone < r.Phone)
        {
            return findFirstPhoneHelper(L->rest, L->first);
        }
        else
        {
            return findFirstPhoneHelper(L->rest, r);
        }
    }
}

//--------------------------------------------------------------------------
// @description find the last name of the student with the smallest Phone
//              number
// @param L a list of student records
// @return "" if L is empty, otherwise, the last name of the student with
//         the smallest Phone number
// @contract findFirstPhone : ListOfStudentRecord -> string
// @example findFirstPhone(empty) == ""
// @example findFirstPhone(&list_1) == "Cruise"
// @example findFirstPhone(&list_2) == "Cruise"
// @example findFirstPhone(&list_3) == "Klimmer"
//--------------------------------------------------------------------------
std::string findFirstPhone(ListOfStudentRecord * L)
{
    if (L == 0)
    {
        return "";
    }
    else
    {
        return findFirstPhoneHelper(L->rest, L->first);
    }
}

Scheme Solution.

;----------------------------------------------------------------------------
; @description find the last name of the student with the smallest Phone
;              number
; @param L a list of student records
; @param r a student record with the smallest Phone number so far
; @return "" if L is empty, otherwise, the last name of the student with
;         the smallest Phone number
; @contract findFirstPhoneHelper : ListOfStudentRecord -> string
; @example (findFirstPhoneHelper empty student_2) = "Pitt"
; @example (findFirstPhoneHelper list_1 student_2) = "Cruise"
; @example (findFirstPhoneHelper list_2 student_2) = "Cruise"
; @example (findFirstPhoneHelper list_3 student_2) = "Klimmer"
;----------------------------------------------------------------------------
(define (findFirstPhoneHelper L r)
  (cond
    [(empty? L) (SR-lastName r)]
    [(< (SR-phone (first L)) (SR-phone r)) (findFirstPhoneHelper (rest L) (first L))]
    [else (findFirstPhoneHelper (rest L) r)]))

;----------------------------------------------------------------------------
; @description find the last name of the student with the smallest Phone
;              number
; @param L a list of student records
; @return "" if L is empty, otherwise, the last name of the student with
;         the smallest Phone number
; @contract findFirstPhone : ListOfStudentRecord -> string
; @example (findFirstPhone empty) = ""
; @example (findFirstPhone list_1) = "Cruise"
; @example (findFirstPhone list_2) = "Cruise"
; @example (findFirstPhone list_3) = "Klimmer"
;----------------------------------------------------------------------------
(define (findFirstPhone L)
  (cond
    [(empty? L) ""]
    [else (findFirstPhoneHelper (rest L) (first L))]))