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

tactic: dsimp [insert, cond]
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
⊢ (m.insert k v).size = (m.insert k v).buckets.size
state_after: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
⊢ (match AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] with
      | true =>
        { size := m.size,
          buckets :=
            m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
      | false =>
        if numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size then
          { size := m.size + 1,
            buckets :=
              m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
        else
          expand (m.size + 1)
            (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).size =
    (match AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] with
        | true =>
          { size := m.size,
            buckets :=
              m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                (AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
        | false =>
          if numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size then
            { size := m.size + 1,
              buckets :=
                m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                  (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
          else
            expand (m.size + 1)
              (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).buckets.size

tactic: split
state_before: α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
⊢ (match AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] with
      | true =>
        { size := m.size,
          buckets :=
            m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
      | false =>
        if numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size then
          { size := m.size + 1,
            buckets :=
              m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
        else
          expand (m.size + 1)
            (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).size =
    (match AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] with
        | true =>
          { size := m.size,
            buckets :=
              m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                (AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
        | false =>
          if numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size then
            { size := m.size + 1,
              buckets :=
                m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                  (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
          else
            expand (m.size + 1)
              (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).buckets.size
state_after: case h_1
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
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,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    { size := m.size,
          buckets :=
            m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.replace k v 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 : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
⊢ (if numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size then
        { size := m.size + 1,
          buckets :=
            m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
      else
        expand (m.size + 1)
          (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).size =
    (if numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size then
          { size := m.size + 1,
            buckets :=
              m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
        else
          expand (m.size + 1)
            (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).buckets.size

tactic: split
state_before: case h_2
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
⊢ (if numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size then
        { size := m.size + 1,
          buckets :=
            m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
      else
        expand (m.size + 1)
          (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).size =
    (if numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size then
          { size := m.size + 1,
            buckets :=
              m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }
        else
          expand (m.size + 1)
            (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).buckets.size
state_after: case h_2.isTrue
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
⊢ { size := m.size + 1,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    { size := m.size + 1,
          buckets :=
            m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.buckets.size

case h_2.isFalse
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : ¬numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
⊢ (expand (m.size + 1)
        (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).size =
    (expand (m.size + 1)
          (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).buckets.size

tactic: unfold Buckets.size
state_before: case h_1
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
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,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    { size := m.size,
          buckets :=
            m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.buckets.size
state_after: case h_1
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
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,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    Nat.sum
      (List.map (fun x => x.toList.length)
        { size := m.size,
                buckets :=
                  m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                    (AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.buckets.val.data)

tactic: refine have ⟨_, _, h₁, _, eq⟩ := Buckets.exists_of_update ..; eq ▸ ?_
state_before: case h_1
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
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,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    Nat.sum
      (List.map (fun x => x.toList.length)
        { size := m.size,
                buckets :=
                  m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                    (AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.buckets.val.data)
state_after: case h_1
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : 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.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ { size := m.size,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    Nat.sum
      (List.map (fun x => x.toList.length)
        (w✝¹ ++ AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝))

tactic: simp [h, h₁, Buckets.size_eq]
state_before: case h_1
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : 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.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ { size := m.size,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    Nat.sum
      (List.map (fun x => x.toList.length)
        (w✝¹ ++ AssocList.replace k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝))
state_after: no goals

tactic: unfold Buckets.size
state_before: case h_2.isTrue
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
⊢ { size := m.size + 1,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    { size := m.size + 1,
          buckets :=
            m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
              (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.buckets.size
state_after: case h_2.isTrue
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
⊢ { size := m.size + 1,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    Nat.sum
      (List.map (fun x => x.toList.length)
        { size := m.size + 1,
                buckets :=
                  m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                    (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.buckets.val.data)

tactic: refine have ⟨_, _, h₁, _, eq⟩ := Buckets.exists_of_update ..; eq ▸ ?_
state_before: case h_2.isTrue
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
⊢ { size := m.size + 1,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    Nat.sum
      (List.map (fun x => x.toList.length)
        { size := m.size + 1,
                buckets :=
                  m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
                    (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.buckets.val.data)
state_after: case h_2.isTrue
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
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.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ { size := m.size + 1,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    Nat.sum
      (List.map (fun x => x.toList.length)
        (w✝¹ ++ AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝))

tactic: simp [h, h₁, Buckets.size_eq, Nat.succ_add]
state_before: case h_2.isTrue
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
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.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝
⊢ { size := m.size + 1,
        buckets :=
          m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯ }.size =
    Nat.sum
      (List.map (fun x => x.toList.length)
        (w✝¹ ++ AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝))
state_after: case h_2.isTrue
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
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.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.cons k v 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✝¹) +
      (m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length +
          Nat.sum (List.map (fun x => x.toList.length) w✝) +
        1)

tactic: rfl
state_before: case h_2.isTrue
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
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.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.cons k v 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✝¹) +
      (m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length +
          Nat.sum (List.map (fun x => x.toList.length) w✝) +
        1)
state_after: no goals

tactic: rw [expand_size]
state_before: case h_2.isFalse
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : ¬numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
⊢ (expand (m.size + 1)
        (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).size =
    (expand (m.size + 1)
          (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
            (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).buckets.size
state_after: case h_2.isFalse
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : ¬numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
⊢ (expand (m.size + 1)
        (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).size =
    (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
        (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).size

tactic: simp only [expand, h, Buckets.size, Array.data_length, Buckets.update_size]
state_before: case h_2.isFalse
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : ¬numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
⊢ (expand (m.size + 1)
        (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
          (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯)).size =
    (m.buckets.update (mkIdx ⋯ (hash k).toUSize).val
        (AssocList.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).size
state_after: case h_2.isFalse
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : ¬numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
⊢ 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.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data)

tactic: refine have ⟨_, _, h₁, _, eq⟩ := Buckets.exists_of_update ..; eq ▸ ?_
state_before: case h_2.isFalse
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : ¬numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
⊢ 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.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data)
state_after: case h_2.isFalse
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : ¬numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
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.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.cons k v 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.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝))

tactic: simp [h₁, Buckets.size_eq, Nat.succ_add]
state_before: case h_2.isFalse
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : ¬numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
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.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.cons k v 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.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] :: w✝))
state_after: case h_2.isFalse
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : ¬numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
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.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.cons k v 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✝¹) +
      (m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length +
          Nat.sum (List.map (fun x => x.toList.length) w✝) +
        1)

tactic: rfl
state_before: case h_2.isFalse
α : Type u_1
β : Type u_2
inst✝¹ : BEq α
inst✝ : Hashable α
m : Imp α β
k : α
v : β
h : m.size = m.buckets.size
c✝ : Bool
heq✝ : AssocList.contains k m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat] = false
h✝ : ¬numBucketsForCapacity (m.size + 1) ≤ m.buckets.val.size
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.cons k v m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat]) ⋯).val.data =
    w✝¹ ++ AssocList.cons k v 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✝¹) +
      (m.buckets.val[(mkIdx ⋯ (hash k).toUSize).val.toNat].toList.length +
          Nat.sum (List.map (fun x => x.toList.length) w✝) +
        1)
state_after: no goals