Fixpoint insert {X} (x : X) (xs : list X) (n : nat) :=
match xs with
| [] => [x]
| y :: ys =>
match n with
| O => x :: xs
| S m => y :: insert x ys m
end
end.
Inductive parts_into {X} : list X -> list X -> list X -> Prop :=
| part_nil : parts_into [] [] []
| parts_cons_l {xs zs} {x} i ys :
parts_into xs ys zs ->
parts_into (x :: xs) (insert x ys i) zs
| parts_cons_r {xs ys} {x} i zs :
parts_into xs ys zs ->
parts_into (x :: xs) ys (insert x zs i).
Goal parts_into [1;2;3;4;5] [5;2] [1;4;3].

(* Specifications: *)
Lemma inListPartition:
forall {A} (a b c: list A) x, In x a \/ In x (b ++ c) -> In x (a ++ b) \/ In x c.
Axiom HleafNodeConst: forall x p leafIdx lvl dt,
isLeafNode x (writeToNode p leafIdx lvl dt) ->
isLeafNode x p.
Lemma zero_sum: forall s memSz leafIdx lvl dt,
match s with
|(s', (l, p)) =>
init_invariant s memSz ->
init_invariant
(s',
(popStash l dt,
writeToNode p leafIdx lvl dt
)
) memSz
end.
Lemma writeBacks_invariant_holds:
forall leafIdx lvl memSz lIDs s,
init_invariant s memSz ->
forall u strm stsh ttr,
(u, (strm, (stsh, ttr))) =
runState (writeBacks leafIdx lIDs lvl) s ->
init_invariant (strm, (stsh, ttr))  memSz.
Lemma access_rec_invariant_holds:
forall (leafIdx: nat) (lIDs : list nat) (lvl:nat) (s : st_rand) (memSz : nat),
init_invariant s memSz ->
forall u strm stsh ttr,  (u, (strm, (stsh, ttr))) = runState (access_rec leafIdx lIDs lvl) s ->
init_invariant (strm, (stsh, ttr)) memSz.
Lemma get_random_nat_invariant_holds:
forall s memSz,
init_invariant s memSz ->
let (_, oldTsPair) := runState (get_random_nat tt) s in
init_invariant oldTsPair memSz.