EBoard 10: Pause for Breath

This class will be recorded! Its use is limited to members of the class. Please do not share with others.

Approximate overview

  • General administrative stuff [~10 min]
  • Q&A [~15 min]
  • Median [~10 min] [Became ~65 min]
  • Lab [~55 min] [Became ~0 min]

Administrative stuff

Notes and News

  • Happy eleven-eleven! It’s Armistice Day and Veteran’s Day.
  • Evening tutoring will be available 3-5 p.m. Sundays and 8-10 p.m. Sundays through Thursdays in the tutoring channel on the CS team.
  • Individual tutors are also available, but we prefer that you try the evening tutors first.
  • For clarity: You can use your labs and such when you do quizzes (and learning assessments).
  • You too can be on the CS mailing list. Just let me know.
  • I’d love to hear questions from more of you.

Upcoming activities

Attend (or watch recording) and send a one-paragraph reflection.

  • Noon, Thursday, Convocation (+1 token, more details Wednesday)
  • 5pm, Thursday, CS Extras (+1 token)

Upcoming work

About the first SoLA

  • I’ll be grading them over the next few days. I hope to release them by the weekend.
  • Please do not discuss them with anyone but me. Someone may be taking an extension or …. Plus, I want to be able to reuse them.
  • Please do not discuss how you did. The end results are usually not positive.
    • “That was pretty straightforward. I think I got all seven right.” (Other person feels bad that they didn’t find it straightforward.)
    • “Wow, that was hard. What did you get on problem 4?” (Other person wants to follow policies. Also, what if they found it easy. How do they respond?)
    • “Sam is evil”

Q&A

The First SoLA

Why “SoLA”?

Set of Learning Assessments.

Also: Part of doremi. A mountain pass (great metaphor, isn’t it)? A plant from which we make pith helmets.

Can I at least say “Sam is evil” or something similar?

Certainly.

But couldn’t you tell from my name? The Rebel from the Sky is …? (Hmmm … How did the folks at Ellis Island feel about my people?)

Mini-project 2

Why doesn’t it work on “4331 4271 4127 4447”?

I don’t know. Why should it?

“It’s my credit card.”

We need to discuss security and privacy.

I think you got the digits backwards.

Yup. I misread the Luhn algorithm. You work from the right (* 2, add digits) rather than the left. So with an odd number of digits, the leftmost digit is also the (* 2, add digits)

I’ll accept either version.

How do I design a test? The algorithm seems complex to run on its own.

I’d choose some simple, obvious things to start with.

The check-value-computation of “1000 0000 0000 000” is ….

The check-value-computation of “0100 0000 0000 000” is ….

The check-value-computation of “0030 0000 0000 000” is ….

The check-value-computation of “0034 0000 0000 000” is ….

The check-value-computation of “0000 0000 0000 009” is ….

The check-value-computation of “7992 7398 7100 000” is ….

The check-value-computation of “0799 2739 8710 000” is ….

Can we assume that we only have to handle sixteen-digits?

Yup. That’s fifteen digits plus a check digit.

Is it okay that I used a different strategy than Sam suggested?

That’s fine. Sam’s is not the only strategy. As long as you’re doing the alternating “digit as is” and “double then add digits”.

Readings

Why use anonymous procedures?

Clean and simple.

May better match how we think about things. “Add 1 and then square.” (o sqr (section + 1 <>))

Often, you have “one-off” procedures; naming things is a PITA.

Beautiful, small, elegant.

Why is (all char-numeric? (string->list "")) true?

What is (string->list "")? It’s the empty list.

Are there non-numeric characters in that list? Nope.

So any characters in that list are numbers.

Similar to (and).

Why is (any char-numeric? (string->list "")) true?

What is (string->list "")? It’s the empty list.

Are there numeric characters in that list? Nope.

So it’s false.

Similar to (or).

Median

“Hammers can be dangerous.”

(define median-of-three
  (lambda (x y z)
    (cond
      [(< x y z) 
       y]
      [(< y x z) 
       x]
      [(< x z y) 
       z]
      [(< z x y)
       x]
      [(< y z x)
       z]
      [(< z y x)
       y]
      [else
       #f])))
  • Seems long. Can we write a shorter version?
  • Maybe we can do it better with something we’ve just talked about.
  • We should try tests. E.g., is (median-of-three 1 2 3) 2?
  • It might be nice to write tests like this (when (not (= 2 (median-of-three 1 2 3))) (error "First check failed"))
  • How can we reach the else? With equal numbers.
  • What is the median of 1, 2, and 1? Maybe 1.5
  • How do you compute a median? For three numbers, you find the middle of the series once they are put in numerical order.
  • Does median alter values? If not, the only possibilities are 1, 2, and 1.5.
  • 1.
  • Whoops! This fails if the numbers are equal. That’s an easy fix.
(define median-of-three
  (lambda (x y z)
    (cond
      [(<= x y z)
       y]
      [(<= y x z)
       x]
      [(<= x z y)
       z]
      [(<= z x y)
       x]
      [(<= y z x)
       z]
      [(<= z y x)
       y]
      [else
       #f])))
  • Is it correct now? Seems to be.
  • How did you to fast editing? I’m using a text editor that lets you type strange arcane commands. :.,.+20s/</<=/s

A better strategy

(define median-of-three
  (lambda (x y z)
    (list-ref (sort (list x y z) <=) 2)))

We can generalize

(define median
  (lambda (lst)
    (list-ref (sort lst <=) ...)))

What’s the index of the middle element? Length divided by 2.

(define median
  (lambda (lst)
    (list-ref (sort lst <=) (/ (length lst) 2))))

Whoops. That failed.

(define median
  (lambda (lst)
    (list-ref (sort lst <=) (quotient (length lst) 2))))

What’s the median of the list ‘(1 2 3 4)?

Whoops. For even-length lists, we take the two middle elements and average them.

Some things you might have learned from that exercise?

  • Medians (media?) are potentially complicated (or more complicated than we thought).
  • There’s more than one way to solve most problems.
  • Simple human operations can be more difficult on the computer.
  • Don’t just assume that your algorithm works by checking it on only one input.
  • Test a lot of values, in a variety of situations. Choose ones that are strategic; different kinds of cases.
  • Help yourself out by writing mini-tests, rather than conducting them by hand.
  • It can be good to generalize.
  • Even experts miss problems. Writing lots of mini-tests is good.
  • Rely on the power of many.
  • Sam will work on helping you think about good checks.

Suppose you hadn’t learned the list operations and compose and section. Is there another way to write “median of three” that’s short and elegant? without conditionals!

Break into smallish groups

And our conclusion is?

(define median-of-three
  (lambda (x y z)
    (max (min x y) (min x z) (min y z))))

Idea: We’ve eliminated the largest value by taking all of the mins. We’ve eliminated the smallest value by taking the max. Ta dah!

Idea: Add all of them together, subtract the minimum and the maximum.

(define median-of-three
  (lambda (x y z)
    (- (+ x y z) (min x y z) (max x y z))))

Time to write more tests!

Think about more interesting tests we haven’t done yet.

  • Negative numbers.
  • Not whole numbers. 0.5
  • Fractions. 1/2 1/3 4/7
  • Complex numbers? (Unfortunately, they don’t have a median)
  • Really large
  • Really small
  • Combination of really large and really small

Final set of code

#lang racket
(require 2htdp/image)
(require csc151)
(require Desktop/csc151-helper)

(define median-of-three-1
  (lambda (x y z)
    (cond
      [(< x y z)
       y]
      [(< y x z)
       x]
      [(< x z y)
       z]
      [(< z x y)
       x]
      [(< y z x)
       z]
      [(< z y x)
       y]
      [else
       #f])))

(define median-of-three-2
  (lambda (x y z)
    (list-ref (sort (list x y z) <=) 1)))

(define median
  (lambda (lst)
    (list-ref (sort lst <=) (quotient (length lst) 2))))

(define median-of-three-3
  (lambda (x y z)
    (max (min x y) (min x z) (min y z))))

(define median-of-three
  (lambda (x y z)
    (- (+ x y z) (min x y z) (max x y z))))


(when (not (equal? 2 (median-of-three 1 2 3)))
  (error "First check failed"))
(when (not (equal? 1 (median-of-three 1 2 1)))
  (error "Second check failed"))
(when (not (equal? 3 (median-of-three 3 2 4)))
  (error "Third check failed"))
(when (not (equal? 7 (median-of-three 7 7 7)))
  (error "Fourt median check failed"))
(when (not (equal? 32 (median-of-three 2 732 32)))
  (error "Next median check failed"))
(when (not (equal? 0 (median-of-three 0 0 0)))
  (error "Next median check failed"))
(when (not (equal? 48 (median-of-three 16 48 92)))
  (error "Next median check failed"))
(when (not (equal? 6 (median-of-three 305 -23 6)))
  (error "Next median check failed"))
; The following check fails on Sam's computer.
;(when (not (equal? 2 (median-of-three 1111111111111111111111111111111111111.5 2 .0000000000000000000000000000000000000032))))
;  (error "Next median check failed"))

(when (not (equal? 2 (median (list 3 1 2))))
  (error "First median check failed"))
(when (not (equal? 3 (median (list 1 2 3 4 5))))
  (error "Second median check failed"))
(when (not (equal? 4 (median (list 7 3 9 2 4))))
  (error "Third median check failed"))
;(when (not (equal? 2.5 (median (list 1 2 3 4))))
;  (error "Fourth median check failed"))
(when (not (equal? 7 (median (list 7 7 7))))
  (error "Fourt median check failed"))
(when (not (equal? 32 (median (list 2 732 32))))
  (error "Next median check failed"))
(when (not (equal? 0 (median (list 0 0 0))))
  (error "Next median check failed"))
(when (not (equal? 48 (median (list 16 48 92))))
  (error "Next median check failed"))
(when (not (equal? 6 (median (list 305 -23 6))))
  (error "Next median check failed"))

Lab

Nope. Sam decided that talking through the median problem was more important than today’s lab. We’ll do it tomorrow. Somehow. So no new reading for tomorrow, either.