Search Monad.
Open Scope monad_scope.
Section Utils.
End Utils.
Section Tree.
(* (***************************************) *)
(* (*************** STASH *****************) *)
(* (***************************************) *)
(* Section STASH. *)
Definition concatStash {A} (stsh : list (prod nat A)) (a : list (prod nat A)) := stsh ++ a.
Inductive BlockEntry : Type := BV(f s: nat).
Definition BlockEntry_fst (be : BlockEntry) : nat :=
match be with
| BV f _ => f
end.
Fixpoint readBlockFromStash (stsh : list BlockEntry) (bID : nat) : option nat :=
match stsh with
| [] => None
| h :: t => match h with
| BV f s => if Nat.eqb f bID
then Some s
else readBlockFromStash t bID
end
end.
Fixpoint updateStash(bID: nat) (dataN: nat)(stsh: list BlockEntry): list BlockEntry :=
match stsh with
| [] => []
| (BV id data) :: t => if Nat.eqb bID id
then (BV id dataN) :: updateStash bID dataN t
else updateStash bID dataN t
end.
Fixpoint popStash (stsh: list BlockEntry) (sublist: list BlockEntry) : list BlockEntry :=
match sublist with
| [] => stsh
| (BV k v) :: t =>
match stsh with
| [] => []
| (BV bID data) :: xs =>
if Nat.eqb k bID
then xs
else popStash stsh t
end
end.
Fixpoint popList {A} (a s : list A) (f : A -> A -> bool): list A :=
match s with
| [] => a
| h :: t => match a with
| [] => []
| x :: xs => if f h x
then popList xs t f
else popList xs s f
end
end.
(* Compute popList [1;2;3;4;5] [1;5;2] Nat.eqb. PROBLEMATIC.*)
(* End STASH. *)
Inductive PBTree (A: Type) : Type :=
| Leaf (idx: nat) (val: A)
| Node (idx: nat) (val: A) (l r: PBTree A).
(* Fixpoint RBTree (A: Type) (l : nat): Type := *)
(*   match l with *)
(*     | O =>  *)
Fixpoint pb (X : Type) (n : nat) : Type :=
match n with
| 0 => unit
| S m => X * pb X m * pb X m
end.
Definition leaf {X} : pb X 0 := tt.
Definition node {X} {n} : X -> pb X n -> pb X n -> pb X (S n) :=
fun x t1 t2 => (x,t1,t2).
Definition example : pb nat 2 :=
node 0
(node 1 leaf leaf)
(node 2 leaf leaf).
Arguments Leaf {_} _ _.
Arguments Node {_} _ _ _ _.
Fixpoint getHeight {A: Type} (root: PBTree A) : nat :=
match root with
| Leaf _ _ => 0
| Node _ _ l r => S (max (getHeight l) (getHeight r))
end.
Fixpoint isPBTree {A} (t : PBTree A) : Prop :=
match t with
| Leaf _ _ => True
| Node _ _ l r => getHeight l = getHeight r
/\ (isPBTree l) /\( isPBTree r)
end.
Fixpoint buildPBTlevelOrder {A} (def_a : A) (label : nat) (ht : nat) : PBTree A :=
match ht with
| 0 => Leaf label def_a
| S ht' => Node label def_a
(buildPBTlevelOrder def_a (2 * label + 1) ht')
(buildPBTlevelOrder def_a (2 * label + 2) ht')
end.
Definition PBTree1 {A} : PBTree (list A) := buildPBTlevelOrder [] 0 3.
Compute PBTree1.
Inductive Dir := L | R.

(* Specifications: *)
Lemma div2 : forall (n : nat), PeanoNat.Nat.div2 n  < S n.
Next Obligation.