#lang racket
(require csc151)

;; CSC 151.02 (Fall 2020, Term 2)
;; Lab: Conditionals (Side A)
;;   https://rebelsky.cs.grinnell.edu/Courses/CSC151/2020Fa2/labs/conditionals
;; Authors: YOUR NAMES HERE
;; Date: THE DATE HERE
;; Acknowledgements:
;;   ACKNOWLEDGEMENTS HERE

#|
This lab consists of a number of programming and reasoning exercises
about booleans and conditionals.  Start with the A-side exercises with
A-side driving and B-side navigating.  Then switch back and forth as
indicated.
|#

; +---------------------------------+--------------------------------
; | Exercise 1: Conditional tracing |
; +---------------------------------+

#|
Consider the following code snippet:
|#

(define foo
  (lambda (x1 x2)
    (if (< x1 x2)
        #t
        #f)))

(define bar
  (lambda (x1 x2)
    (< x1 x2)))

#|
Give execution traces for each of the following expressions.  Check
with the interactions pane that your final value coincides with the
result of evaluating the expression in Racket.

(a) (foo 2 4)

<TODO: give your trace here>

(b) (foo 5 3)

<TODO: give your trace here>

(c) (bar 2 4)

<TODO: give your trace here>

(d) (bar 5 3)

<TODO: give your trace here>

(e) What is the difference between foo and bar?

<TODO: give your answer here>

|#

; +-------------------------+----------------------------------------
; | Exercise 4: Boolean Zen |
; +-------------------------+

#|
(a)
In a previous exercise, you wrote a function `even?` that determines
whether a number is even.  Consider the following functions that uses
`even?` to determine if both of its parameters are even.
|#

(define really-bad-both-even?
  (lambda (n1 n2)
    (if (equal? (even? n1) #t)
        (if (equal? (even? n2) #t)
            #t
            #f)
        #f)))

#|
For example:

> (really-bad-both-even? 2 4)
#t
> (really-bad-both-even? 1 2)
#f

We claim that this implementation is "really bad" not because it
produces the wrong answer, but is is sylistically gross!  First,
rewrite this function as `bad-both-even?` below using `and` and `or`
to remove the need for a nested conditional expression.

Experiment with `bad-both-even?` on a variety of examples to gain
confidence that your function works identically to
`really-bad-both-even?`.
|#

(define bad-both-even?
  (lambda (n1 n2)
    {??}
))

#|
(b) If your implementation of `bad-both-even?` still contains a
conditional, then you still have more work to do!  Rewrite the
function one more time as `both-even?` below that uses no conditionals
in its implementation.  Again, experiement with `both-even?` and a
variety of examples to ensure that it works identically to the
previous implementations.
|#

(define both-even?
  (lambda (n1 n2)
    {??}
))

#|
(c) The process of reimplementing `both-even?` so that it is better
designed while keeping its behaviror the same is called refactoring.
Refactoring this function tells us something profound about booleans
and expressions, a concept that I picked up from Stuart Reges at the
Unviersity of Washington called "boolean zen."

Suppose that I have a piece of code that looks as follows:

(if <expr> #t #f)

Where `<expr>` is an arbitrary expression.  Based on `both-even?`,
describe what I can rewrite this code to that is equivalent to the
original version but more concise.  In a few sentences, describe and
justify your answer.

<TODO: give your rewritten code and explanation here!>
|#

#|
(d) Finally, use the concept of boolean zen to write a concise version
of the function `(both-odd? n1 n2)` that returns true only when both
of its arguments are odd integers.  (N.B., simply negating
`both-even?` won't work since `both-even?` will return false if one
argument is even and the other is odd!)
|#

(define both-odd?
  (lambda (n1 n2)
    {??}
))

; +---------------------------------------------+--------------------
; | Exercise 5: Mixing conditionals and strings |
; +---------------------------------------------+

#|
In this exercise, we continue learning how to work with the primitive
types and their standard library functions.  Use functions from the
Racket standard library to implement the following common functions
that utilize booleans.

When you are done, you should experiment with your function in the
interactions pane on a variety of inputs to verify that the program
works as expected.
|#

#|
(a) In a particular company, employees are given IDs that consist of
a string of 6 digits, e.g., "419109".  The founders of the company
are given IDs where the first 3 digits are 0s, e.g., "000110".

Write a function, `(employee-id? str)`, that takes a string as input
and determines whether the string is a valid employee id.  You need
not check that `str` is a string.

> (employee-id? "123456")
#t
> (employee-id? "1")
#f
> (employee-id? "000111")
#t
> (employee-id? "00011x")
#f
> (employee-id? 123456)
Boom!  Crash!
|#

; TODO: write your function here!

#|
(b) Write a function `(founder-id? s)` that takes a string as input and
determines whether the string is a valid founder's ID.
|#

; TODO: write your function here!

