Require Import Bool Nat.

(** **** Exercise: 1 star, standard (nandb)

    The [Admitted] command can be used as a placeholder for an
    incomplete proof.  We use it in exercises to indicate the parts
    that we're leaving for you -- i.e., your job is to replace
    [Admitted]s with real proofs.

    Remove "[Admitted.]" and complete the definition of the following
    function; then make sure that the [Example] assertions below can
    each be verified by Coq.  (I.e., fill in each proof, following the
    model of the [orb] tests above, and make sure Coq accepts it.) The
    function should return [true] if either or both of its inputs are
    [false].

    Hint: if [simpl] will not simplify the goal in your proof, it's
    probably because you defined [nandb] without using a [match]
    expression. Try a different definition of [nandb], or just
    skip over [simpl] and go directly to [reflexivity]. We'll
    explain this phenomenon later in the chapter. *)

Definition nandb (b1:bool) (b2:bool) : bool
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.

Example test_nandb1:               (nandb true false) = true.
(* FILL IN HERE *) Admitted.
Example test_nandb2:               (nandb false false) = true.
(* FILL IN HERE *) Admitted.
Example test_nandb3:               (nandb false true) = true.
(* FILL IN HERE *) Admitted.
Example test_nandb4:               (nandb true true) = false.
(* FILL IN HERE *) Admitted.

(** **** Exercise: 1 star, standard (xorb) 
  Complete the definition of the xorb function below, which should implement the
  xor (exclusive or) operation. Write four Example tests that test the full truth
  table for xor, and make sure your definition passes them. If it doesn't, consider:
  is your function wrong, or is the test wrong?
*)

Definition xorb (b1:bool) (b2:bool) : bool
  (* := ... *). Admitted.
(*
Example test_xorb1:
Example test_xorb2:
Example test_xorb3:
Example test_xorb4:
*)

(** **** Exercise: 1 star, standard (factorial)

    Recall the standard mathematical factorial function:

       factorial(0)  =  1
       factorial(n)  =  n * factorial(n-1)     (if n>0)

    Translate this into Coq.

    Make sure you put a [:=] between the header we've provided and
    your definition.  If you see an error like "The reference
    factorial was not found in the current environment," it means
    you've forgotten the [:=]. *)

Fixpoint factorial (n:nat) : nat
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.

Example test_factorial1:          (factorial 3) = 6.
(* FILL IN HERE *) Admitted.
Example test_factorial2:          (factorial 5) = (mult 10 12).
(* FILL IN HERE *) Admitted.

(** **** Exercise: 1 star, standard (plus_id_exercise)

    Remove "[Admitted.]" and fill in the proof.  (Note that the
    theorem has _two_ hypotheses -- [n = m] and [m = o] -- each to the
    left of an implication arrow.) *)

Theorem plus_id_exercise : forall n m o : nat,
  n = m -> m = o -> n + m = m + o.
Proof.
  (* FILL IN HERE *) Admitted.

(** **** Exercise: 1 star, standard (zero_nbeq_plus_mult_1) *)
Theorem zero_nbeq_plus_mult_1 : forall n : nat,
  0 =? ((n + 1) * 1) = false.
Proof.
  (* FILL IN HERE *) Admitted.

(** **** Exercise: 1 star, standard (identity_fn_applied_twice)

    Use the tactics you have learned so far to prove the following
    theorem about boolean functions. *)

Theorem identity_fn_applied_twice :
  forall (f : bool -> bool),
  (forall (x : bool), f x = x) ->
  forall (b : bool), f (f b) = b.
Proof.
  (* FILL IN HERE *) Admitted.

(** [] *)

(** **** Exercise: 1 star, standard (negation_fn_applied_twice)

    Now state and prove a theorem [negation_fn_applied_twice] similar
    to the previous one but where the second hypothesis says that the
    function [f] has the property that [f x = negb x]. *)

(* FILL IN HERE *)

(* Grad exercise *)
(* Here are two more ways to represent colors as an inductive data type.
   color1 lists eight colors: *)
Inductive color1 :=
| red
| orange
| yellow
| green
| blue
| purple
| black
| white.

(* color2 records the presence or absence of each of three colors as a boolean: *)
Inductive color2 :=
| RYB (red : bool) (yellow : bool) (blue : bool).

(* The following function translates the first representation to the second,
   by marking the presence or absence of red, yellow, and blue in each color. *)
Definition color1_to_color2 (c : color1) : color2 :=
  match c with
  | red => RYB true false false
  | orange => RYB true true false
  | yellow => RYB false true false
  | green => RYB false true true
  | blue => RYB false false true
  | purple => RYB true false true
  | black => RYB false false false
  | white => RYB true true true
  end.

(* Write a function color2_to_color1 that performs the opposite conversion. *)

(* Prove that if we convert a color from color1 to color2 and back,
   we get the same color we started with. *)
