Choose c = 2 and n_{0} = 3. Then, we have (n + 3) ≤ 2n which simplifies to 3 ≤ n which is true for all n ≥ 3.
Choose c = 1 and n_{0} = 0. Then, we have n + 3 ≥ n which is true for all n.
Choose c = 2 and n_{0} = 1. Then, we have (n^{2} + n) ≤ 2n^{2} which simplifies to n ≤ n^{2} and 1 ≤ n, which is true for all n > 1.
Choose c = 1 and n_{0} = 0. Then we have (n^{2} + n) > n^{2} which is true for all n > 0.
Choose c = 1 and n_{0} = 0. Then we have 2^{n} ≤ 3^{n} which is true for all n > 0.
Since 3^{n} grows faster than 2^{n} for any choice of c, we can always find a value m such that 2^{n} < c * 3^{n} for all n > m.
Recall that 2^{n} is 2 * 2 * 2 * ... (n times) and 3^{n} is 3 * 3 * 3 ... (n times). So, we need to choose n such that c * 3 * 3 * 3 ... (n times) is greater than 2 * 2 * ... (n times). Each time we increase the value of n by one, the value of c3^{n} / 2^{n} is multiplied by 1.5. After some number of multiplications, it must be greater than 1.
Choose c = 1 and n_{0} = 2. Then, we have 2^{n} ≤ n^{n} for all n ≥ 2.
Since n^{n} grows faster than 2^{n} for any choice of c, we can always find a value m such that 2^{n} < cn^{n} for all n > m. For example, we can choose n = 1/c + 1.
Then, cn^{n} = c1/c^{1/c + 1} = 1/c^{1/c}. Since c must be less than 1/2 (otherwise n = 3 would work), we know 1/c > 2, and 1/c^{1/c} ≥ 2^{1/c}.
a. Draw the global environment after the following expressions are evaluated:
(define t1 (mcons 'name 'email)) (set-mcar! t1 'nom) (set-mcdr! t1 'courriel) (set-mcdr! t1 t1)
Hence, the global environment looks like:
a. Define post-item! as a procedure that takes two parameters (name, description) and adds an entry with the given name and description to the items table.
(define (post-item! name description) (table-insert! items (list name description)))
The body of post-item! is (table-insert! items (list name description)). The (list name description) evaluation is constant time since the time it takes to make a cons cell does not depend on the sizes of its inputs. The table-insert! procedure is defined as:
(define (table-insert! table entry) ;;; The entry must have the right number of values --- one for each field in the table (assert (= (length entry) (length (table-fields table)))) (if (null? (table-entries table)) (set-mcdr! (tlist-get-data 'table table) (mlist entry)) (mlist-append! (table-entries table) (mlist entry))) (void)) ;;; don't evaluate to a valueThe assert involves two applications of length, which (at least as we defined list-length) has running time in Θ(N) where N is the length of the input list. Here, the inputs are both fixed sizes, so the running time is constant. The evaluations of (table-entries table), (set-mcdr! (tlist-get-data 'table table) (mlist entry)), and (mlist entry) are also all constant time. They do not depend on anything whose size varies. So, we only need to consider the evaluation of (mlist-append! (table-entries table) (mlist entry))). The running time of mlist-append! is linear in the length of its first input (as analyzed in class, we need to mcdr down the first input list until we find the last mcons cell). In this case, that is the number of entries in the table. The table passed into table-insert! is items, so the total running time is in Θ (N_{items}) where N_{items} is the number of entries in the items table.
a. Define insert-bid! as a procedure that takes three parameters (bidder, item and amount) and adds a corresponding entry to the bids table.
(define (insert-bid! bidder item amount) (table-insert! bids (list bidder item amount)))
Our insert-bid! procedure applies table-insert! to the bids table and the new bid. Creating the new bid using list and the three operands is in Θ(1). The table-insert! procedure includes (mlist-append! (table-entries table) (mlist entry))). The mlist-append! procedure, defined in Example 9.4, has a running time in Θ(N) where N is the number of elements in the first input list. Hence, insert-bid! has running time in Θ(N_{bids}) where N_{bids} is the number of entries in the bids table.
a. Define the table-select procedure.
(define (table-select table field predicate) (let ((fieldno (table-field-number table field))) (if (= fieldno 0) (error "No matching field" field) (make-table (table-fields table) (mlist-filter (lambda (entry) (predicate (list-get-element entry fieldno))) (table-entries table)))))
The make-table, table-fields and table-entries are constant time. The mlist-filter procedure needs to look at every element in its input list, so its running time is in Θ(N) where N is the number of elements in the input list. This assumes the filter input procedure is constant time. If the number of fields in the table is constant, then that is the case. Thus, the total work is in Θ(N_{table}) where N_{table} is the number of entires in the input table.
If the number of fields is not constant, then we need to consider how the work required by table-field-number and list-get-element scales with the selected field. Both procedures need to cdr down a list until the matching entry is found. Hence, they have running times in Θ(M) where M is the number of elements in the input list.
As it is used in table-select it is the number of fields in the table in both cases. Hence, the total work is in Θ(N_{table}F_{table}) where N_{table} is the number of entries in the table argument and F_{table} is the number of fields in the table argument. In most cases, though, it would be reasonable to assume the number of fields is bounded (since we don't usually add more fields to a table), hence the running time is in in Θ(N_{table}).
a. 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. If there is no bid, return null. You shouldn't assume that the last entry that is a bid on this item is the highest bid for that item.
(define (get-highest-bid item) (let ((fieldno (table-field-number bids 'amount)) (entries (table-entries (table-select bids 'item-name (make-string-selector item))))) (if (null? entries) null (mlist-find-best (lambda (bid1 bid2) (> (list-get-element bid1 fieldno) (list-get-element bid2 fieldno))) entries))))
b. Describe the asymptotic running time of your get-highest-bid procedure using Θ notation. Be careful to specify carefully what any variables you use in your answer mean.
The get-highest-bid evaluates (get-bids item). This selects matching bids from the bids table. Since table-select has running time in Θ(N_{table}) where N_{table} is the number of entries in the table (question 5b), this has running time in Θ(N_{bids}) where N_{bids} is the number of entries in the bids table.
The length of the resulting list is on average (/ N_{bids} N_{items}) since all bids are for items in the table. Since the length of the list is N_{bids}/N_{items}, the work required by the get-highest-bid procedure is in Θ(N_{bids}/N_{items}).
But, get-highest-bid has to do both the work of get-bids and then get-highest-bid, so its total work is in Θ(N_{bids} + N_{bids}/N_{items} ). Since N_{items} is positive, the first term will dominate in the asympotitic operator, so the running time is in Θ(N_{bids}).
(define (place-bid! bidder item amount) (let ((bidder-entry (table-entries (table-select bidders 'name (make-string-selector bidder)))) (item-entry (table-entries (table-select items 'item-name (make-string-selector item)))) (highest-bid (get-highest-bid item))) (if (= (mlength bidder-entry) 0) (error bidder " is not a legitimate bidder!") (if (> (mlength bidder-entry) 1) (error "Multiple matching bidders named: " bidder) (if (= (mlength item-entry) 0) (error item " is not for sale!") (if (> (mlength item-entry) 1) (error "Multiple matching items: " item) (if (or (null? highest-bid) (> amount (list-get-element highest-bid (table-field-number bids 'amount)))) (begin (insert-bid! bidder item amount) true) (error "Bid amount does not exceed previous highest bid: " highest-bid))))))))Question 8:
a. Define a procedure end-auction! that reports the final auction results. You may assume that the auction has been conducted fairly (i.e., using place-bid! and not by randomly mutating the tables). For each item in the auction, your procedure should print out a message indicating who won the item and for what price, or that there were no bits on the item.
(define (end-auction!) (mlist-sum (mmap (lambda (item-entry) (let ((item-name (list-get-element item-entry (table-field-number items 'item-name)))) (let ((high-bid (get-highest-bid item-name))) (if (null? high-bid) (begin (printf "No bids on ~a.~n" (list-get-element item-entry (table-field-number items 'item-name))) 0) (begin (printf "Congratulations ~a! You have won the ~a for $~a.~n" (list-get-element high-bid (table-field-number bids 'bidder-name)) item-name (list-get-element high-bid (table-field-number bids 'amount))) (list-get-element high-bid (table-field-number bids 'amount))))))) (table-entries items))))
b. Describe the running time of your end-auction! procedure. (You answer should use Θ notation, should clearly define the meaning of all variables you use in your answer, and should include a convincing explanation of why it is correct.)
Our end-auction! procedure uses mmap with the input list (table-entries items). The mmap procedure has running time in Θ(N) where N is the number of elements in the input list. But, this assumes the amount of work done for each item is constant. In end-auction! it is not constant though! For each item, the mapping procedure evaluates (get-highest-bid item-name), as well as list-get-element twice. The list-get-element procedure has running time in Θ(V) where V is the value of its second parameter, since it needs to cdr down the list V times to find the V^{th} element. In both cases, V is constant though, since it is the result of (table-field-number bids 'bidder-name) or (table-field-number bids 'amount). Hence, we only need to worry about how much work (get-highest-bid item-name) requires.
As analyzed in question 6b, the running time of get-highest-bid is in Θ(N_{bids}).
Evaluating end-auction! evaluates get-highest-bid once for each item, so we need to multiply the number of items times the time for each item. Thus, the total running time is in Θ(N_{items} × N_{bids}). Note that this should make us believe there is a more efficient way to implement end-auction!. It is doing some redundant work, since it looks through the entire bids table for each item (hence, looking at each bid N_{items} times, instead of just once). It should be possible to implement end-auction! with running time in Θ(N_{items} + N_{bids}), but this would be more complicated (and worth a gold star bonus!).
You must be logged in to post a comment.