---
title: Eboard 24  Randomness and simulation
number: 24
section: eboards
held: 2018-03-16
link: true
---
CSC 151.01, Class 24:  Randomness and simulation
================================================

_Overview_

* Preliminaries
    * Notes and news
    * Upcoming work
    * Extra credit
    * Friday PSA
    * Questions
* Quiz
* Debrief from prior class
* Lab
* Debrief

Preliminaries
-------------

### News / Etc.

* New partners!
* You are still awesome.
* I know that some of you were planning to look at last semester's
  exam 3 to study for the coming exam 3.  Unfortunately, that exam
  depends on some material we haven't studied yet.  
    * Problems 1, 2, and 4 are of the style that might appear on the
      exam.
    * You are not yet ready to do problem 4.  I am not yet certain
      whether or not we will choose to include vectors on the exam.
* Have a great spring break!

### Upcoming work

* There is no writeup for today's class.
* Reading for Monday after break
    * [Pairs and pair structures](../readings/pairs)
* No homework over break.
* Exam 3 will be distributed after break.
    * Yes, you will get exam 2 (and an answer key) back first.

### Extra credit (Academic/Artistic)

* Visit the two exhibits at the Faulconer Gallery.

### Extra credit (Peer)

### Extra credit (Recurring peer)

* Listen to KDIC Wednesdays at 6pm - Witty banter with other 
  personalities and/or co-host.  Also Indian, Arabic, and Farsi music.  
  (Up to two units of extra credit.)
* Peer editing with SS.  Talk to SS about the details.  Make your
  English Lit more literate.

### Extra credit (Misc)

* Host one or more prospective students.  

### Other good things

### Friday / Spring Break PSA

* Please take care of yourselves.
* If you imbibe substances, do so in moderation (and, preferably, legally)
* If you cohabit, consent is absolutely positively necessary
    * It's the right thing

### Questions

_It feels like it would be easier to use a `define` in the body of
the procedure, rather than named let or `letrec`.  Can't I just do
that?_

> There are some semantic confusions with using `define` in the body
of a procedure.  So we do not permit it.  (We do discuss the idea of
using `define` rather than `let` every few years.  We always decide to
do without it.)

_Could you go over named let?  I find it confusing._

> Sure.

> Named let is intended to provide a "more natural" syntax for something
  that you do a lot of.  (a) Define a recursive (helper) procedure;
  (b) call that procedure.

> When we think about solving problems with helpers and tail recursion,
  a table helps us think.

> When we design the table, we often name columns and think about their
  initial values.

> Named let is intended to mimic that, but in Scheme syntax.

```
(let NAME ([PARAM1 VAL1]
           [PARAM2 VAL2]
           ...)
  BODY)
```

> The other important issue about table-based solutions is that we say
  "Do it all again, updating each parameter as follows."  Amazingly,
  a procedure call makes sense for that.

```
(NAME (INSTRUCTIONS-FOR-UPDATING-COLUMN-1)
      (INSTRUCTIONS-FOR-UPDATING-COLUMN-2)
      ...)
```

_What do I put in for `val1` and `val2` and ..._

> Answer one: If you think in terms of our traditionally way of writing
a recursive helper.

```
(define helper
  (lambda (PARAM1 PARAM2 ...)
    BODY))

(define primary-procedure
  (lambda (...)
    (helper EXP1 EXP2 ...)))
```

> If you can write that, it translates directly to

```
(define primary-procedure
  (lambda(...)
    (let helper ([PARAM1 EXP1]
                 [PARAM2 EXP2]
                 ...)
       BODY))
```

> But if you want to think about it more directly, think in terms of the table.
  VAL1 etc. are what I put in the first row of the table.

_What is the relationship between the body of the primary procedure and
the body of the named-let procedure?_

> There is none.  Each is independent.  (Although the body of the primary
  procedure likely depends on the implementation of the named-let.)

_Where is the first call to the procedure defined in the named let?_

> It is implicit.

_If we don't check preconditions, can we still use named let and is
there anything else there?_

> Yes, you can still used named let.  Often, you'll see nothing else.

```
(define tally-odds
  (lambda (lst)
    (let table ([tally-so-far 0]
                [remaining lst])
      (cond
        [(null? remaining)
         tally-so-far]
        [(and (integer? (car remaining))
              (odd? (car remaining)))
         (table (+ 1 tally-so-far)
                (cdr remaining))]
        [else
         (table tally-so-far
                (cdr remaining))]))))
```

_What if we're checking preconditions?_

```
(define tally-odds
  (lambda (lst)
    (cond
      [(not (list? lst))
       (error "You are listless!")]
      [(not (all integer? lst))
       (error "You lack integrity")]
      [else
        (let table ([tally-so-far 0]
                    [remaining lst])
          (cond
            [(null? remaining)
             tally-so-far]
            [(odd? (car remaining))
             (table (+ 1 tally-so-far)
                    (cdr remaining))]
            [else
             (table tally-so-far
                    (cdr remaining))]))])))
```

_Can I use the parameters of the primary procedure in the body of the 
let?_

> Yes.  Sometimes, it even helps you shrink your code.  Consider our
normal approach to iota, which involves counting up to n.  Since the
n doesn't change, it doesn't need to be a parameter to the (local) kernel.

```
(define iota
  (lambda (n)
    (let kernel ([i 0])
      (if (= i n)
          null
          (cons i (kernel (+ i 1)))))))
```

_Does named let do anything fancy other than let you define a procedure and
call it immediately?_

> Nope. But "define a procedure and call it immediately" is a really common
  task.

Quiz
----

Wow, Sam screwed up a lot.

* Two missing names.
* One misspelled name.
* Two missing students. [+1 for that student]
* [+1 for everyone for Sam's screwups; this may be the highest scoring quiz
  in history]

Debrief from prior class
------------------------

_We spent enough time on preliminary questions that I'm skipping this one._

Let's look at the different ways people approached problem 2 (finding
the furthest from zero using a local kernel), particularly the different
places they put the kernel.

```
(define ff0
  (letrec ([kernel ...])
    (lambda (lst)
      (cond
        ...))))

(define ff0
  (lambda (lst)
    (letrec ([kernel ...])
      (cond 
        ...))))

(define ff0
  (lambda (lst)
    (cond
      ...
      [else
       (letrec ([kernel ...])
         ...)])))
```

Which do you prefer?  Why?

Which is easiest to change to named let?

Lab
---

It is hard to test random procedures, since they don't have predictable
output.  (We could do a lot of calls and see if they meet a reasonable
statistical distribution.)

Yes, we really do want you to use direct recursion on the first procedure.

These are zero-parameter procedures.  They are procedures because we are
encapsulating a series of steps.  They have no parameters because they
need no inputs.

When you see "Rolling ... Rolling ... Rolling ...", do you think

* "on the river"?
* "Rawhide"?
* None of the above?

If this question does not make sense, look for a YouTube Video of Ike and
Tina Turner singing "Proud Mary" and the Blues Brothers singing "Rawhide".

Debrief
-------

The problem with `tally-7-11`?  We have two calls to `(pair-a-dice)`.
Sometimes both are called.  Sometimes only one.

Lots of ways to write `tally-sevens-elevens`.

```
(define tally-7-11
  (lambda (n)
    (let ([this-roll (pair-a-dice)])
      (cond
        [(zero? n)
         0]
        [(or (= 7 this-roll) (= 11 this-roll))
         (+ 1 (tally-7-11 (- n 1)))]
        [else
         (tally-7-11 (- n 1))]))))

; That first version does one extra roll.  We should make sure that `n`
; is not zero before rolling.

(define tally-7-11
  (lambda (n)
    (cond
      [(zero? n)
       0]
      [(let ([this-roll (pair-a-dice)])
         (or (= 7 this-roll) (= 11 this-roll)))
       (+ 1 (tally-7-11 (- n 1)))]
      [else
       (tally-7-11 (- n 1))])))

; That second version is kind of ugly.  The old `count-odd-rolls?` was much
; nicer.  Can we follow that model?  We can if we write a helper procedure.

(define seven-or-eleven?
  (lambda (roll)
    (or (= 7 roll) (= 11 roll))))

(define tally-7-11
  (lambda (n)
    (cond 
      [(zero? n)
       0]
      [(seven-or-eleven? (pair-a-dice))
       (+ 1 (tally-7-11 (- n 1)))]
      [else
       (tally-7-11 (- n 1))])))

; Can we do without a new procedure?

(define tally-7-11
  (lambda (n)
    (cond
      [(zero? n)
       0]
      [(member? (pair-a-dice) '(7 11))
       (+ 1 (tally-7-11 (-n 1)))]
      [else
       (tally-7-11 (- n 1))])))

; Or if we love section

(define tally-7-11
  (lambda (n)
    (cond
      [(zero? n)
       0]
      [((disjoin (section = 7 <>) (section = 11 <>)) (pair-a-dice))
       (+ 1 (tally-7-11 (-n 1)))]
      [else
       (tally-7-11 (- n 1))])))
```
