University of Virginia, Department of Computer Science
CS200: Computer Science, Spring 2003

Problem Set 5: Wahoo! Auctions Out: 24 February 2003
Due: Friday, 14 March 2003, 5pm

Collaboration Policy - Read Carefully

You may work on this assignment by yourself or with one other student of your choice.

Regardless of whether you work alone or with a partner, you are encouraged to discuss this assignment with other students in the class and ask and provide help in useful ways. You may consult any outside resources you wish including books, papers, web sites and people. If you use resources other than the class materials, indicate what you used along with your answer.

You have nearly three weeks to complete this problem set. It would be highly unwise to wait until after Spring Break to start it.

We recommend you take advantage of these staffed lab hours:

Wednesday, 26 February: 7-8:30pm (Rachel)
Thursday, 27 February: 6:30-8pm (Katie)
More lab hours will be posted on the course web site after Spring Break.

Purpose

Reading: SICP, Chapter 3-3.3.2 (p. 217-261).

Download: Download ps5.zip to your machine and unzip it into your home directory J:\cs200\ps5.

This file contains:

  • ps5.ss — A template for your answers. You should do the problem set by editing this file.
  • database.ss — Partial implementation of a database.
  • listprocs.ss — Some useful procedures for manipulating lists (you have seen most of them already in class).

Background

Once upon a time, in a faraway fictional town known as Charlottansville, East Virginia, there was a highly regarded public university where funding cuts led to a budget crisis. The wise and noble University administration tried cutting "non-essential" services such as heat and cleaning for student housing, libraries, printing and professors and have attempted some more creative solutions including hiring more administrators, building a fancy new basketball arena, increasing student tuition, installing fancy electronic scoreboards on the intramural sports fields, increasing student housing fees, hiring professional football coaches, and hiring even more administrators, but somehow the budget is still not balanced. The Board of Transients has decided the time for drastic measures has arrived, and they will conduct an auction to raise money. To avoid paying fees to a commercial auction service, they have asked you do develop an auction service for them.

The auction service will be built using a database. A database is just a way of storing and manipulating a large amount of structured data. For this problem set, you will implement a database and use it to implement an auction service. Our database is controlled using Scheme procedures that are similar to the SQL commands used to control nearly all commercial databases. In Problem Set 8, you will build a dynamic web site that uses SQL commands to interact with a database.

Data in a database is stored in tables. The fields of a table describe the data and are not mutable. The entries of a table are the data, and can be changed. We will represent a table using a cons pair where the car is a list of the table fields and the cdr is a list of the table entries. These definitions are found in database.ss:

     (define (make-new-table fieldlist) (cons fieldlist null))
     (define (make-table fieldlist entries) (cons fieldlist entries))
     (define (table-fields table) (car table))
     (define (table-entries table) (cdr table))
For the Wahoo! Auctions service, we will need several different tables to keep track of the bidders, the items for sale, and the bids on those items. We use quoted symbols to describe the fields in a table. Those tables are defined in ps5.ss:
     (define bidders (make-new-table (list 'name 'email)))
     (define items (make-new-table (list 'item-name 'description)))
     (define bids (make-new-table (list 'bidder-name 'item-name 'amount)))
Question 1: Draw the global environment after (define bidders (make-new-table (list 'name 'email))) is evaluated.

Question 2:
a. Draw the global environment after the following expressions are evaluated (starting in a clean global environment where make-new-table, table-fields and table-entries are defined as above):
   (define t1 (make-new-table (list 'name 'email)))
   (set-car! (table-fields t1) 'nom)
   (set-cdr! t1 t1)
b. Suppose we then evaluate:
   (define (length lst) (if (null? lst) 0 (+ 1 (length (cdr lst)))))
   (length t1)
Explain why the evaluation of (length t1) never terminates.

Try evaluating the expressions in Question 2 in DrScheme. Also evaluate t1 and see if you can figure out what the printed value means.

Inserting Entries

In Question 2, we manipulated our tables using set-car! and set-cdr!. It is awkward and error-prone to manipulate our database that way. Instead, we want to define more abstract procedures for manipulating data tables.

The table-insert! procedure inserts an entry into a table. We follow the Scheme (and Yahoo!?) convention of using an ! at the end of the names of procedures that mutate state. You should follow this convention also.

You shouldn't need to change the definition of table-insert!, but you should be able to understand it (defined in database.ss):

(define (table-insert! table entry)
  (assert (= (length entry) (length (table-fields table))))
  (if (null? (table-entries table))
      (set-cdr! table (list entry))
      (append! (table-entries table) (list entry)))
  (void)) ;;; don't evaluate to a value
The expression (assert (= (length entry) (length (table-fields table)))) checks that the entry we are adding to the table has the right number of elements — there must be one element in the entry corresponding to each field in the table. The assert procedure will produce an error if the passed parameter is false. It is defined:
(define (assert pred)
  (if (not pred) (error "Assertion failed!")))
We use (void) at the end of the procedure body to prevent an application of table-insert! from evaluating to a value.

Question 3:
a. Why does the definition of table-insert! use append! instead of append? (Your answer should clearly explain what would go wrong if we used append.)

b. Why does the definition of table-insert! need to do something different in the case where (table-entries table) is null? Hint: try evaluating

    (define lst null) 
    (append! lst 3) 
    lst
Note that DrScheme's append! behaves differently then the append! defined in SICP Exercise 3.12.

Our auction service will need procedures for adding bidders, posting items for sale and bidding on items. For now, define simple procedures that insert entries in the appropriate tables:

Question 4: Define add-bidder, post-item and insert-bid.

We have provided a table-display procedure in database.ss for printing out a table. You don't need to understand the details of how table-display works, but you should figure out how we used the make-constant-function (from last year's Exam 1) in it.

If you define add-bidder, post-item and insert-bid correctly, you should obtain the following interactions:

> (table-display bidders)

name                       email                      
-------------------------  -------------------------  

> (add-bidder "Tim Koogle" "tk@yahoo.com")

> (add-bidder "Katie Couric" "katie@nbc.com")

> (add-bidder "Dave Matthews" "dave@dmb.com")

> (table-display bidders)

name                       email                     
-------------------------  ------------------------- 
Tim Koogle                 tk@yahoo.com              
Katie Couric               katie@nbc.com
Dave Matthews              dave@dmb.com              
Develop similar tests for your post-item and insert-bid procedures, and make sure they also work correctly.

Selecting Entries

Inserting entries in tables is only useful if we can also get the entries we are interested in out of the table. The table-select procedure takes a table, a field and a procedure. It evaluates to a table that has the same fields as the input table, and has entries that are all entries in the table for with the procedure applied to the value of the field for that entry is true. For example, in ps5.ss we define:
  (define (make-string-selector match)
    (lambda (fval) (string=? fval match)))

  (define (get-bids item)
    (table-entries (table-select bids 'item-name (make-string-selector item))))
The get-bids procedure evaluates to a list of bid entries that are the entries in the bids table whose item-name field matches the parameter item. If you're not sure how this works, try evaluating some expressions using make-string-selector by themselves.

Question 5: Define the table-select procedure. You may find the find-element-number, get-nth and filter procedures defined in listprocs.ss useful (but are not required to use them).

If your table-select is working correctly, you should see the following interactions:

> (insert-bid "Tim Koogle" "SEAS" 10000000)

> (insert-bid "Dave Matthews" "CLAS" 2000000)

> (insert-bid "Katie Couric" "SEAS" 15000000)

> (table-select bids 'item-name (lambda (pitem) (string=? pitem "CLAS")))

((bidder-name item-name amount) ("Dave Matthews" "CLAS" 2000000))

> (table-display (table-select bids 'item-name (lambda (pitem) (string=? pitem "CLAS"))))

bidder-name                item-name                  amount                     
-------------------------  -------------------------  -------------------------  
Dave Matthews              CLAS                       2000000                    

> (table-entries (table-select bids 'item-name (lambda (pitem) (string=? pitem "SEAS"))))

(("Tim Koogle" "SEAS" 10000000) ("Katie Couric" "SEAS" 15000000))

> (table-entries (table-select bids 'item-name (lambda (pitem) (string=? pitem "Rotunda"))))

()

> (table-entries (table-select bids 'amount (lambda (pamount) (> pamount 10000000))))

(("Katie Couric" "SEAS" 15000000))

> (table-entries (table-select bids 'amount (lambda (pamount) (<= pamount 10000000))))

(("Tim Koogle" "SEAS" 10000000) ("Dave Matthews" "CLAS" 2000000))

> (table-entries
    (table-select
      (table-select bids 'amount (lambda (pamount) (<= pamount 10000000)))
      'bidder-name
      (lambda (pbidder) (string=? pbidder "Tim Koogle"))))

(("Tim Koogle" "SEAS" 10000000))

Selects can be nested. Here we use (table-select bids 'amount (lambda (pamount) (<= pamount 10000000))) to produce the table of all bids over 10000000, and then use another table-select to select the bids from that table where the bidder name is "Tim Koogle". To make sure you understand table-select, produce a different expression that will evaluate to the same table by selecting the name first and then the amount.

Remember our University is completely fictional. The bid amounts should not be construed to have anything to do with the actual value of any aspects of any real Universities with which you might be familiar (or with the generosity of actual University alumni who might have similar names).

Cancelling Bids

Before an auction concludes, a bidder can cancel a bid. To implement bid cancelation, we need to be able to delete entries from the bids table. For this, define a table-delete! procedure. Like table-select it should take three parameters: a table, a field and a procedure. But instead of evaluating to a list of the entries in the table that satisfy the selection procedure, table-delete! should remove those entries from the table.

Question 6: Define a table-delete! procedure that removes entries from a table.

If your table-delete! procedure is correct the cancel-bids procedure defined in ps5.ss should delete all bids by bidder from the bids table:

(define (cancel-bids bidder)
  (table-delete! bids 'bidder-name (make-string-selector bidder)))
Here are some sample interactions using table-delete! for testing your procedure:

> (setup-tables)

> (table-display bidders)

name                                     email                                    
-------------------------                -------------------------                
Tim Koogle                               tk@yahoo.com                             
Katie Couric                             katie@nbc.com                            
Dave Matthews                            dave@dmb.com                             

> (table-delete! bidders 'name (make-string-selector "Dave Matthews"))

> (table-display bidders)

name                                     email                                    
-------------------------                -------------------------                
Tim Koogle                               tk@yahoo.com                             
Katie Couric                             katie@nbc.com                            

> (table-delete! bidders 'name (make-constant-function #t))

name                                     email                                    
-------------------------                -------------------------                

> (table-display bids)

bidder-name                item-name                  amount                     
-------------------------  -------------------------  -------------------------  
Tim Koogle                 SEAS                       10000000                   
Dave Matthews              CLAS                       2000000                    
Katie Couric               SEAS                       15000000                   
Tim Koogle                 SEAS                       12000000                   

> (cancel-bids "Tim Koogle")

> (table-display bids)

bidder-name                item-name                  amount                     
-------------------------  -------------------------  -------------------------  
Dave Matthews              CLAS                       2000000                    
Katie Couric               SEAS                       15000000                   

Placing Bids

To conduct fair auctions, we can't just allow any bid to be inserted into the bids table. Instead, bids will be placed using a place-bid procedure. It should:
Question 7: Define a get-highest-bid procedure that takes an item name as a parameter and evaluates to the bid entry that is the highest bid on that item. You shouldn't assume that the last entry that is a bid on this item is the highest bid for that item.

Hint: consider sorting the list a table-select evaluates to.

Your get-highest-bid procedure should work like this:

> (setup-tables)

> (get-highest-bid "SEAS")

("Katie Couric" "SEAS" 15000000)

> (get-highest-bid "CLAS")

("Dave Matthews" "CLAS" 2000000)

> (get-highest-bid "Rotunda")

()

Question 8: Define a new place-bid procedure that satisfies the description above. Don't attempt to do everything at once! Start by satisfying one of the properties first and testing your procedure before trying to satisfy the other property.

You should get interactions similar to these:

> (setup-tables)

> (place-bid "Tim Koogle" "SEAS" 20000000)

Tim Koogle is now the high bidder for SEAS: 20000000

> (place-bid "Katie Couric" "SEAS" 18000000)

Bid amount does not exceed previous highest bid: (Tim Koogle SEAS 20000000)

> (table-display bids)

bidder-name                item-name                  amount                     
-------------------------  -------------------------  -------------------------  
Tim Koogle                 SEAS                       10000000                   
Dave Matthews              CLAS                       2000000                    
Katie Couric               SEAS                       15000000                   
Tim Koogle                 SEAS                       12000000                   
Tim Koogle                 SEAS                       20000000                   

> (place-bid "Katie Couric" "SEAS" 22000000)

Katie Couric is now the high bidder for SEAS: 22000000

> (place-bid "Dave Matthews" "AFC" 1000000)

Dave Matthews is now the high bidder for AFC: 1000000

> (place-bid "Dave Matthews" "Rotunda" 1000000)

The Rotunda is not for sale!

> (place-bid "Dave Evans" "SEAS" 10000000000)

Dave Evans is not an authorized bidder!

Ending the Auction

When the auction is over, all items are sold to the highest bidders and the University collects the high bid amounts. If there are no bids for an item, it cannot be sold.

The value university-funds is defined in ps5.ss. It stores the amount of money available to the University. Initially, it is -12000000 to represent a $12M deficit. When an auction ends, the high bid for each item that is sold is added to the university-funds.

Question 9: Define a procedure end-auction! that completes the auction. It should go through every item in the items table. If there are no bids on the item, the item remains unsold. If there are any bids, the item is sold to the highest bidder and the value of university-funds increases by the amount of the high bid. Your end-auction! procedure should print out information about the winning bidder for each item.

Here's an example:

> (setup-tables)

> university-funds

-12000000

> (place-bid "Tim Koogle" "SEAS" 18000000)

Tim Koogle is now the high bidder for SEAS: 18000000

> (place-bid "Katie Couric" "CLAS" 1000)

Bid amount does not exceed previous highest bid: (Dave Matthews CLAS 2000000)

> (cancel-bids "Dave Matthews")

> (place-bid "Katie Couric" "CLAS" 1000)

Katie Couric is now the high bidder for CLAS: 1000

> (end-auction!)

Congratulations Tim Koogle!  You have won the SEAS for $18000000.
   Please drop off the cash under Mr. Jefferson's statue.
Congratulations Katie Couric!  You have won the CLAS for $1000.
   Please drop off the cash under Mr. Jefferson's statue.
No bids on AFC.
No bids on MEC.
Wahoo!  The University is no longer in deficit and has $6001000 to spend 
on a system for hiding the empty seats in the new basketball arena. 

> university-funds

6001000

Try some sample auctions to demonstrate your program. See if you can make enough money to save the University, but be careful not to sell off too many important assets — we will revisit the University in Charlottansville in Problem Set 6.

Credits: This problem set was created for CS200 Spring 2003 by Katie Winstanley, Rachel Dada, Spencer Stockdale and David Evans. Any similarity between the events depicted in this problem set and the goings on at a real University are purely coincidental, especially the parts about hiring more administrators and the Board of Visitors deciding to spend thousands of dollars to hide empty seats in the new basketball arena at the same meeting where they discussed increasing student housing rates because the first year dorms are deteriorating.

CS 200


CS 200: Computer Science
Department of Computer Science
University of Virginia

Circle Fractal by Ramsey Arnaoot and Qi Wang

cs200-staff@cs.virginia.edu
Using these Materials