Inductive bin : Type :=
| Z
| B0 (n : bin)
| B1 (n : bin).
Fixpoint incr (m:bin) : bin :=
match m with
| Z => B1 Z
| B0 m' => B1 m'
| B1 m' => B0 (incr m')
end.
Fixpoint bin_to_nat (m:bin) : nat :=
match m with
| Z => O
| B0 m' => 2 * (bin_to_nat m')
| B1 m' => 1 + 2 * (bin_to_nat m')
end.
(*  Prove that the following diagram commutes: incr bin ----------------------> bin |                           | bin_to_nat |                           |  bin_to_nat |                           | v                           v nat ----------------------> nat  *)
Fixpoint nat_to_bin (n:nat) : bin :=
match n with
| O => Z
| S n' => incr (nat_to_bin n')
end.
Fixpoint double (n:nat) :=
match n with
| O => O
| S n' => S (S (double n'))
end.
Definition double_bin (b:bin) : bin :=
match b with
| Z => Z
| _ => B0 b
end.
(* Define normalize. You will need to keep its definition as simple as possible for later proofs to go smoothly. Do not use bin_to_nat or nat_to_bin, but do use double_bin. *)
(* make sure you use double_bin *)
Fixpoint normalize (b: bin) : bin :=
match b with
| Z => Z
| B0 b' => match b' with
| Z => Z
| _ => double_bin (normalize b')
end
| B1 b' => incr (double_bin (normalize b'))
end.
Fixpoint zero_n (n: nat) : bin :=
match n with
| O => Z
| S n' => B0 (zero_n n')
end.
Fixpoint append_bin (b: bin) (base: bin) : bin :=
match b with
| Z => base
| B0 b' => B0 (append_bin b' base)
| B1 b' => B1 (append_bin b' base)
end.
Definition insert_n_zeros_before (b: bin) (n: nat) : bin :=
append_bin b (zero_n n).

Lemma double_bin_incr: forall b, double_bin (incr b) = incr (incr (double_bin b)).