(* (***************************************) *)
(* (*************** 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).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).(* 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).(* 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).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.Inductive Dir := L | R.Inductive Dir := L | R.Inductive Dir := L | R.

Lemma div2 : forall (n : nat), PeanoNat.Nat.div2 n < S n.