Ltac lookup_insert :=
  first [
    rewrite lookup_insert_bingo by omega
  | rewrite lookup_insert_old by omega; one_plus_x_minus_one
  | rewrite lookup_insert_recent by omega
  | rewrite lookup_shift_insert
  ].Ltac lookup_insert_all :=
  first [
    rewrite lookup_insert_bingo in * by omega;
    try match goal with h: Some _ = Some _ |- _ => injection h; intro; subst; clear h end
  | rewrite lookup_insert_old in * by omega; one_plus_x_minus_one
  | rewrite lookup_insert_recent in * by omega
  | rewrite lookup_shift_insert in *
  ].

(* Specifications: *)
Lemma map_empty: forall A B (f : A -> B), map f (@empty _) = @empty _.
Lemma lookup_map_none: forall A B x e (f : A -> B), lookup x e = None -> lookup x (map f e) = None.
Lemma lookup_map_some: forall A B x a e (f : A -> B), lookup x e = Some a -> lookup x (map f e) = Some (f a).
Lemma lookup_map_some_reverse: forall A B x b e (f : A -> B), lookup x (map f e) = Some b -> exists a, lookup x e = Some a /\ b = f a.