Theorem: Batteries.HashMap.Imp.erase_size
File: .lake/packages/batteries/Batteries/Data/HashMap/WF.lean

tactic: dsimp [erase, cond]
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
⊢ (m.erase k).size = (m.erase k).buckets.size
state_after: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
⊢ (match AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] with
      | true =>
        { size := m.size - 1,
          buckets :=
            m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
      | false => { size := m.size, buckets := m.buckets }).size =
    (match AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] with
        | true =>
          { size := m.size - 1,
            buckets :=
              m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
        | false => { size := m.size, buckets := m.buckets }).buckets.size

tactic: split
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
⊢ (match AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] with
      | true =>
        { size := m.size - 1,
          buckets :=
            m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
      | false => { size := m.size, buckets := m.buckets }).size =
    (match AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] with
        | true =>
          { size := m.size - 1,
            buckets :=
              m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
        | false => { size := m.size, buckets := m.buckets }).buckets.size
state_after: case h_1
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
⊢ { size := m.size - 1,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    { size := m.size - 1,
          buckets :=
            m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.buckets.size

case h_2
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
⊢ { size := m.size, buckets := m.buckets }.size = { size := m.size, buckets := m.buckets }.buckets.size

tactic: next H =>
simp only [h, Buckets.size]
refine have ⟨_, _, h₁, _, eq⟩ := Buckets.exists_of_update ..; eq ▸ ?_
simp only [h₁, Array.data_length, Array.ugetElem_eq_getElem, List.map_append, List.map_cons,
  Nat.sum_append, Nat.sum_cons, AssocList.toList_erase]
rw [(_ : List.length _ = _ + 1), Nat.add_right_comm]; {rfl}
clear h₁ eq
simp only [AssocList.contains_eq, List.any_eq_true] at H
have ⟨a, h₁, h₂⟩ := H
refine have ⟨_, _, _, _, _, h, eq⟩ := List.exists_of_eraseP h₁ h₂; eq ▸ ?_
simp [h]; rfl
state_before: case h_1
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
⊢ { size := m.size - 1,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    { size := m.size - 1,
          buckets :=
            m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.buckets.size
state_after: no goals

tactic: simp only [h, Buckets.size]
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
⊢ { size := m.size - 1,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    { size := m.size - 1,
          buckets :=
            m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.buckets.size
state_after: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
⊢ Nat.sum (List.map (fun x => x.toList.length) m.buckets.val.data) - 1 =
    Nat.sum
      (List.map (fun x => x.toList.length)
        (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data)

tactic: refine have ⟨_, _, h₁, _, eq⟩ := Buckets.exists_of_update ..; eq ▸ ?_
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
⊢ Nat.sum (List.map (fun x => x.toList.length) m.buckets.val.data) - 1 =
    Nat.sum
      (List.map (fun x => x.toList.length)
        (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data)
state_after: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
h₁ : m.buckets.val.data = w✝¹ ++ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val] :: w✝
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
eq :
  (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ Nat.sum (List.map (fun x => x.toList.length) m.buckets.val.data) - 1 =
    Nat.sum
      (List.map (fun x => x.toList.length)
        (w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝))

tactic: simp only [h₁, Array.data_length, Array.ugetElem_eq_getElem, List.map_append, List.map_cons,
  Nat.sum_append, Nat.sum_cons, AssocList.toList_erase]
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
h₁ : m.buckets.val.data = w✝¹ ++ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val] :: w✝
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
eq :
  (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ Nat.sum (List.map (fun x => x.toList.length) m.buckets.val.data) - 1 =
    Nat.sum
      (List.map (fun x => x.toList.length)
        (w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝))
state_after: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
h₁ : m.buckets.val.data = w✝¹ ++ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val] :: w✝
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
eq :
  (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ Nat.sum (List.map (fun x => x.toList.length) w✝¹) +
        (m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length +
          Nat.sum (List.map (fun x => x.toList.length) w✝)) -
      1 =
    Nat.sum (List.map (fun x => x.toList.length) w✝¹) +
      ((List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList).length +
        Nat.sum (List.map (fun x => x.toList.length) w✝))

tactic: rw [(_ : List.length _ = _ + 1), Nat.add_right_comm]
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
h₁ : m.buckets.val.data = w✝¹ ++ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val] :: w✝
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
eq :
  (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ Nat.sum (List.map (fun x => x.toList.length) w✝¹) +
        (m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length +
          Nat.sum (List.map (fun x => x.toList.length) w✝)) -
      1 =
    Nat.sum (List.map (fun x => x.toList.length) w✝¹) +
      ((List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList).length +
        Nat.sum (List.map (fun x => x.toList.length) w✝))
state_after: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
h₁ : m.buckets.val.data = w✝¹ ++ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val] :: w✝
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
eq :
  (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ Nat.sum (List.map (fun x => x.toList.length) w✝¹) + (?n + Nat.sum (List.map (fun x => x.toList.length) w✝) + 1) - 1 =
    Nat.sum (List.map (fun x => x.toList.length) w✝¹) +
      ((List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList).length +
        Nat.sum (List.map (fun x => x.toList.length) w✝))

case n
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
h₁ : m.buckets.val.data = w✝¹ ++ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val] :: w✝
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
eq :
  (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ Nat

α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
h₁ : m.buckets.val.data = w✝¹ ++ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val] :: w✝
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
eq :
  (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length = ?n + 1

tactic: {rfl}
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
h₁ : m.buckets.val.data = w✝¹ ++ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val] :: w✝
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
eq :
  (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ Nat.sum (List.map (fun x => x.toList.length) w✝¹) + (?n + Nat.sum (List.map (fun x => x.toList.length) w✝) + 1) - 1 =
    Nat.sum (List.map (fun x => x.toList.length) w✝¹) +
      ((List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList).length +
        Nat.sum (List.map (fun x => x.toList.length) w✝))

case n
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
h₁ : m.buckets.val.data = w✝¹ ++ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val] :: w✝
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
eq :
  (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ Nat

α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
h₁ : m.buckets.val.data = w✝¹ ++ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val] :: w✝
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
eq :
  (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length = ?n + 1
state_after: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
h₁ : m.buckets.val.data = w✝¹ ++ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val] :: w✝
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
eq :
  (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length =
    (List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList).length + 1

tactic: clear h₁ eq
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
h₁ : m.buckets.val.data = w✝¹ ++ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val] :: w✝
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
eq :
  (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length =
    (List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList).length + 1
state_after: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
⊢ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length =
    (List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList).length + 1

tactic: simp only [AssocList.contains_eq, List.any_eq_true] at H
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
⊢ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length =
    (List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList).length + 1
state_after: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
w✝¹ w✝ : List (AssocList α β)
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
H : ∃ x, x ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList ∧ (x.fst == k) = true
⊢ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length =
    (List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList).length + 1

tactic: have ⟨a, h₁, h₂⟩ := H
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
w✝¹ w✝ : List (AssocList α β)
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
H : ∃ x, x ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList ∧ (x.fst == k) = true
⊢ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length =
    (List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList).length + 1
state_after: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
w✝¹ w✝ : List (AssocList α β)
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
H : ∃ x, x ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList ∧ (x.fst == k) = true
a : α × β
h₁ : a ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList
h₂ : (a.fst == k) = true
⊢ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length =
    (List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList).length + 1

tactic: refine have ⟨_, _, _, _, _, h, eq⟩ := List.exists_of_eraseP h₁ h₂; eq ▸ ?_
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
w✝¹ w✝ : List (AssocList α β)
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
H : ∃ x, x ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList ∧ (x.fst == k) = true
a : α × β
h₁ : a ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList
h₂ : (a.fst == k) = true
⊢ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length =
    (List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList).length + 1
state_after: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h✝ : m.size = m.buckets.size
c✝ : Bool
w✝⁴ w✝³ : List (AssocList α β)
left✝² : w✝⁴.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
H : ∃ x, x ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList ∧ (x.fst == k) = true
a : α × β
h₁ : a ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList
h₂ : (a.fst == k) = true
w✝² : α × β
w✝¹ w✝ : List (α × β)
left✝¹ : ∀ (b : α × β), b ∈ w✝¹ → ¬(b.fst == k) = true
left✝ : (w✝².fst == k) = true
h : m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList = w✝¹ ++ w✝² :: w✝
eq : List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList = w✝¹ ++ w✝
⊢ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length = (w✝¹ ++ w✝).length + 1

tactic: simp [h]
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h✝ : m.size = m.buckets.size
c✝ : Bool
w✝⁴ w✝³ : List (AssocList α β)
left✝² : w✝⁴.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
H : ∃ x, x ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList ∧ (x.fst == k) = true
a : α × β
h₁ : a ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList
h₂ : (a.fst == k) = true
w✝² : α × β
w✝¹ w✝ : List (α × β)
left✝¹ : ∀ (b : α × β), b ∈ w✝¹ → ¬(b.fst == k) = true
left✝ : (w✝².fst == k) = true
h : m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList = w✝¹ ++ w✝² :: w✝
eq : List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList = w✝¹ ++ w✝
⊢ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length = (w✝¹ ++ w✝).length + 1
state_after: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h✝ : m.size = m.buckets.size
c✝ : Bool
w✝⁴ w✝³ : List (AssocList α β)
left✝² : w✝⁴.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
H : ∃ x, x ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList ∧ (x.fst == k) = true
a : α × β
h₁ : a ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList
h₂ : (a.fst == k) = true
w✝² : α × β
w✝¹ w✝ : List (α × β)
left✝¹ : ∀ (b : α × β), b ∈ w✝¹ → ¬(b.fst == k) = true
left✝ : (w✝².fst == k) = true
h : m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList = w✝¹ ++ w✝² :: w✝
eq : List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList = w✝¹ ++ w✝
⊢ w✝¹.length + (w✝.length + 1) = w✝¹.length + w✝.length + 1

tactic: rfl
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h✝ : m.size = m.buckets.size
c✝ : Bool
w✝⁴ w✝³ : List (AssocList α β)
left✝² : w✝⁴.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
H : ∃ x, x ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList ∧ (x.fst == k) = true
a : α × β
h₁ : a ∈ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList
h₂ : (a.fst == k) = true
w✝² : α × β
w✝¹ w✝ : List (α × β)
left✝¹ : ∀ (b : α × β), b ∈ w✝¹ → ¬(b.fst == k) = true
left✝ : (w✝².fst == k) = true
h : m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList = w✝¹ ++ w✝² :: w✝
eq : List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList = w✝¹ ++ w✝
⊢ w✝¹.length + (w✝.length + 1) = w✝¹.length + w✝.length + 1
state_after: no goals

tactic: rfl
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
H : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = true
w✝¹ w✝ : List (AssocList α β)
h₁ : m.buckets.val.data = w✝¹ ++ m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val] :: w✝
left✝ : w✝¹.length = (mkIdx ⋯ (hash k).toUSize).val.toNat
eq :
  (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.erase k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ Nat.sum (List.map (fun x => x.toList.length) w✝¹) + (?n + Nat.sum (List.map (fun x => x.toList.length) w✝) + 1) - 1 =
    Nat.sum (List.map (fun x => x.toList.length) w✝¹) +
      ((List.eraseP (fun x => x.fst == k) m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList).length +
        Nat.sum (List.map (fun x => x.toList.length) w✝))
state_after: no goals

tactic: exact h
state_before: case h_2
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
⊢ { size := m.size, buckets := m.buckets }.size = { size := m.size, buckets := m.buckets }.buckets.size
state_after: no goals