Theorem: Std.HashMap.Imp.expand_size
File: Std/Data/HashMap/WF.lean

tactic: rw [expand, go]
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
⊢ Bucket.size (expand sz buckets).buckets = Bucket.size buckets

tactic: rw [Bucket.mk_size]
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
⊢ Nat.sum (List.map (fun x => List.length (AssocList.toList x)) buckets.val.data) +
      Bucket.size (Bucket.mk (Array.size buckets.val * 2)) =
    Bucket.size buckets

tactic: simp [Bucket.size]
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
⊢ Nat.sum (List.map (fun x => List.length (AssocList.toList x)) buckets.val.data) + 0 = Bucket.size buckets

tactic: intro.
state_before: case hs
α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
⊢ ∀ (j : Nat), j < 0 → List.getD buckets.val.data j AssocList.nil = AssocList.nil

tactic: unfold expand.go
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
⊢ Bucket.size (expand.go i source target) =
    Nat.sum (List.map (fun x => List.length (AssocList.toList x)) source.data) + Bucket.size target

tactic: split
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
⊢ Bucket.size
      (if h : i < Array.size source then
        let idx := { val := i, isLt := h };
        let es := Array.get source idx;
        let source := Array.set source idx AssocList.nil;
        let target := AssocList.foldl reinsertAux target es;
        expand.go (i + 1) source target
      else target) =
    Nat.sum (List.map (fun x => List.length (AssocList.toList x)) source.data) + Bucket.size target

tactic: refine (go (i+1) _ _ fun j hj => ?a).trans ?b <;> simp
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
⊢ Bucket.size
      (let idx := { val := i, isLt := H };
      let es := Array.get source idx;
      let source := Array.set source idx AssocList.nil;
      let target := AssocList.foldl reinsertAux target es;
      expand.go (i + 1) source target) =
    Nat.sum (List.map (fun x => List.length (AssocList.toList x)) source.data) + Bucket.size target

tactic: simp [List.getD_eq_get?, List.get?_set]
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
j : Nat
hj : j < i + 1
⊢ List.getD (List.set source.data i AssocList.nil) j AssocList.nil = AssocList.nil

tactic: split
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
j : Nat
hj : j < i + 1
⊢ Option.getD (if i = j then Option.map (fun x => AssocList.nil) (List.get? source.data j) else List.get? source.data j)
      AssocList.nil =
    AssocList.nil

tactic: cases List.get? .. <;> rfl
state_before: case inl
α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
j : Nat
hj : j < i + 1
h✝ : i = j
⊢ Option.getD (Option.map (fun x => AssocList.nil) (List.get? source.data j)) AssocList.nil = AssocList.nil

tactic: next H => exact hs _ (Nat.lt_of_le_of_ne (Nat.le_of_lt_succ hj) (Ne.symm H))
state_before: case inr
α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
j : Nat
hj : j < i + 1
h✝ : ¬i = j
⊢ Option.getD (List.get? source.data j) AssocList.nil = AssocList.nil

tactic: exact hs _ (Nat.lt_of_le_of_ne (Nat.le_of_lt_succ hj) (Ne.symm H))
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H✝ : i < Array.size source
j : Nat
hj : j < i + 1
H : ¬i = j
⊢ Option.getD (List.get? source.data j) AssocList.nil = AssocList.nil

tactic: case b =>
refine have ⟨l₁, l₂, h₁, _, eq⟩ := List.exists_of_set' H; eq ▸ ?_
simp [h₁, Bucket.size_eq]
rw [Nat.add_assoc, Nat.add_assoc, Nat.add_assoc]; congr 1
(conv => rhs; rw [Nat.add_left_comm]); congr 1
rw [← Array.getElem_eq_data_get]
have := @reinsertAux_size α β _; simp [Bucket.size] at this
induction source[i].toList generalizing target <;> simp [*, Nat.succ_add]; rfl
state_before: case b
α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
⊢ Nat.sum (List.map (fun x => List.length (AssocList.toList x)) (List.set source.data i AssocList.nil)) +
      Bucket.size (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])) =
    Nat.sum (List.map (fun x => List.length (AssocList.toList x)) source.data) + Bucket.size target

tactic: refine have ⟨l₁, l₂, h₁, _, eq⟩ := List.exists_of_set' H; eq ▸ ?_
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
⊢ Nat.sum (List.map (fun x => List.length (AssocList.toList x)) (List.set source.data i AssocList.nil)) +
      Bucket.size (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])) =
    Nat.sum (List.map (fun x => List.length (AssocList.toList x)) source.data) + Bucket.size target

tactic: simp [h₁, Bucket.size_eq]
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
l₁ l₂ : List (AssocList α β)
h₁ : source.data = l₁ ++ List.get source.data { val := i, isLt := H } :: l₂
left✝ : List.length l₁ = i
eq : List.set source.data i AssocList.nil = l₁ ++ AssocList.nil :: l₂
⊢ Nat.sum (List.map (fun x => List.length (AssocList.toList x)) (l₁ ++ AssocList.nil :: l₂)) +
      Bucket.size (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])) =
    Nat.sum (List.map (fun x => List.length (AssocList.toList x)) source.data) + Bucket.size target

tactic: rw [Nat.add_assoc, Nat.add_assoc, Nat.add_assoc]
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
l₁ l₂ : List (AssocList α β)
h₁ : source.data = l₁ ++ List.get source.data { val := i, isLt := H } :: l₂
left✝ : List.length l₁ = i
eq : List.set source.data i AssocList.nil = l₁ ++ AssocList.nil :: l₂
⊢ Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₁) +
        Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₂) +
      Nat.sum
        (List.map (fun x => List.length (AssocList.toList x))
          (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])).val.data) =
    Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₁) +
        (List.length (AssocList.toList (List.get source.data { val := i, isLt := H })) +
          Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₂)) +
      Nat.sum (List.map (fun x => List.length (AssocList.toList x)) target.val.data)

tactic: congr 1
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
l₁ l₂ : List (AssocList α β)
h₁ : source.data = l₁ ++ List.get source.data { val := i, isLt := H } :: l₂
left✝ : List.length l₁ = i
eq : List.set source.data i AssocList.nil = l₁ ++ AssocList.nil :: l₂
⊢ Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₁) +
      (Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₂) +
        Nat.sum
          (List.map (fun x => List.length (AssocList.toList x))
            (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])).val.data)) =
    Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₁) +
      (List.length (AssocList.toList (List.get source.data { val := i, isLt := H })) +
        (Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₂) +
          Nat.sum (List.map (fun x => List.length (AssocList.toList x)) target.val.data)))

tactic: (conv => rhs; rw [Nat.add_left_comm])
state_before: case e_a
α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
l₁ l₂ : List (AssocList α β)
h₁ : source.data = l₁ ++ List.get source.data { val := i, isLt := H } :: l₂
left✝ : List.length l₁ = i
eq : List.set source.data i AssocList.nil = l₁ ++ AssocList.nil :: l₂
⊢ Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₂) +
      Nat.sum
        (List.map (fun x => List.length (AssocList.toList x))
          (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])).val.data) =
    List.length (AssocList.toList (List.get source.data { val := i, isLt := H })) +
      (Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₂) +
        Nat.sum (List.map (fun x => List.length (AssocList.toList x)) target.val.data))

tactic: congr 1
state_before: case e_a
α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
l₁ l₂ : List (AssocList α β)
h₁ : source.data = l₁ ++ List.get source.data { val := i, isLt := H } :: l₂
left✝ : List.length l₁ = i
eq : List.set source.data i AssocList.nil = l₁ ++ AssocList.nil :: l₂
⊢ Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₂) +
      Nat.sum
        (List.map (fun x => List.length (AssocList.toList x))
          (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])).val.data) =
    Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₂) +
      (List.length (AssocList.toList (List.get source.data { val := i, isLt := H })) +
        Nat.sum (List.map (fun x => List.length (AssocList.toList x)) target.val.data))

tactic: rw [← Array.getElem_eq_data_get]
state_before: case e_a.e_a
α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
l₁ l₂ : List (AssocList α β)
h₁ : source.data = l₁ ++ List.get source.data { val := i, isLt := H } :: l₂
left✝ : List.length l₁ = i
eq : List.set source.data i AssocList.nil = l₁ ++ AssocList.nil :: l₂
⊢ Nat.sum
      (List.map (fun x => List.length (AssocList.toList x))
        (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])).val.data) =
    List.length (AssocList.toList (List.get source.data { val := i, isLt := H })) +
      Nat.sum (List.map (fun x => List.length (AssocList.toList x)) target.val.data)

tactic: have := @reinsertAux_size α β _
state_before: case e_a.e_a
α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
l₁ l₂ : List (AssocList α β)
h₁ : source.data = l₁ ++ List.get source.data { val := i, isLt := H } :: l₂
left✝ : List.length l₁ = i
eq : List.set source.data i AssocList.nil = l₁ ++ AssocList.nil :: l₂
⊢ Nat.sum
      (List.map (fun x => List.length (AssocList.toList x))
        (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])).val.data) =
    List.length (AssocList.toList source[i]) +
      Nat.sum (List.map (fun x => List.length (AssocList.toList x)) target.val.data)

tactic: simp [Bucket.size] at this
state_before: case e_a.e_a
α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
l₁ l₂ : List (AssocList α β)
h₁ : source.data = l₁ ++ List.get source.data { val := i, isLt := H } :: l₂
left✝ : List.length l₁ = i
eq : List.set source.data i AssocList.nil = l₁ ++ AssocList.nil :: l₂
this : ∀ (data : Bucket α β) (a : α) (b : β), Bucket.size (reinsertAux data a b) = Nat.succ (Bucket.size data)
⊢ Nat.sum
      (List.map (fun x => List.length (AssocList.toList x))
        (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])).val.data) =
    List.length (AssocList.toList source[i]) +
      Nat.sum (List.map (fun x => List.length (AssocList.toList x)) target.val.data)

tactic: induction source[i].toList generalizing target <;> simp [*, Nat.succ_add]
state_before: case e_a.e_a
α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
l₁ l₂ : List (AssocList α β)
h₁ : source.data = l₁ ++ List.get source.data { val := i, isLt := H } :: l₂
left✝ : List.length l₁ = i
eq : List.set source.data i AssocList.nil = l₁ ++ AssocList.nil :: l₂
this :
  ∀ (data : Bucket α β) (a : α) (b : β),
    Nat.sum (List.map (fun x => List.length (AssocList.toList x)) (reinsertAux data a b).val.data) =
      Nat.succ (Nat.sum (List.map (fun x => List.length (AssocList.toList x)) data.val.data))
⊢ Nat.sum
      (List.map (fun x => List.length (AssocList.toList x))
        (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])).val.data) =
    List.length (AssocList.toList source[i]) +
      Nat.sum (List.map (fun x => List.length (AssocList.toList x)) target.val.data)

tactic: rfl
state_before: case e_a.e_a.cons
α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
l₁ l₂ : List (AssocList α β)
h₁ : source.data = l₁ ++ List.get source.data { val := i, isLt := H } :: l₂
left✝ : List.length l₁ = i
eq : List.set source.data i AssocList.nil = l₁ ++ AssocList.nil :: l₂
this :
  ∀ (data : Bucket α β) (a : α) (b : β),
    Nat.sum (List.map (fun x => List.length (AssocList.toList x)) (reinsertAux data a b).val.data) =
      Nat.succ (Nat.sum (List.map (fun x => List.length (AssocList.toList x)) data.val.data))
head✝ : α × β
tail✝ : List (α × β)
tail_ih✝ :
  ∀ (target : Bucket α β),
    Nat.sum
        (List.map (fun x => List.length (AssocList.toList x))
          (List.foldl (fun d x => reinsertAux d x.fst x.snd) target tail✝).val.data) =
      List.length tail✝ + Nat.sum (List.map (fun x => List.length (AssocList.toList x)) target.val.data)
target : Bucket α β
⊢ List.length tail✝ + Nat.succ (Nat.sum (List.map (fun x => List.length (AssocList.toList x)) target.val.data)) =
    Nat.succ (List.length tail✝ + Nat.sum (List.map (fun x => List.length (AssocList.toList x)) target.val.data))

tactic: conv => rhs; rw [Nat.add_left_comm]
state_before: case e_a
α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : i < Array.size source
l₁ l₂ : List (AssocList α β)
h₁ : source.data = l₁ ++ List.get source.data { val := i, isLt := H } :: l₂
left✝ : List.length l₁ = i
eq : List.set source.data i AssocList.nil = l₁ ++ AssocList.nil :: l₂
⊢ Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₂) +
      Nat.sum
        (List.map (fun x => List.length (AssocList.toList x))
          (List.foldl (fun d x => reinsertAux d x.fst x.snd) target (AssocList.toList source[i])).val.data) =
    List.length (AssocList.toList (List.get source.data { val := i, isLt := H })) +
      (Nat.sum (List.map (fun x => List.length (AssocList.toList x)) l₂) +
        Nat.sum (List.map (fun x => List.length (AssocList.toList x)) target.val.data))

tactic: rw [(_ : Nat.sum _ = 0), Nat.zero_add]
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : ¬i < Array.size source
⊢ Bucket.size target = Nat.sum (List.map (fun x => List.length (AssocList.toList x)) source.data) + Bucket.size target

tactic: rw [← (_ : source.data.map (fun _ => .nil) = source.data)]
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : ¬i < Array.size source
⊢ Nat.sum (List.map (fun x => List.length (AssocList.toList x)) source.data) = 0

tactic: refine List.ext_get (by simp) fun j h₁ h₂ => ?_
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : ¬i < Array.size source
⊢ List.map (fun x => AssocList.nil) source.data = source.data

tactic: simp
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : ¬i < Array.size source
j : Nat
h₁ : j < List.length (List.map (fun x => AssocList.nil) source.data)
h₂ : j < List.length source.data
⊢ List.get (List.map (fun x => AssocList.nil) source.data) { val := j, isLt := h₁ } =
    List.get source.data { val := j, isLt := h₂ }

tactic: have := (hs j (Nat.lt_of_lt_of_le h₂ (Nat.not_lt.1 H))).symm
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : ¬i < Array.size source
j : Nat
h₁ : j < List.length (List.map (fun x => AssocList.nil) source.data)
h₂ : j < List.length source.data
⊢ AssocList.nil = List.get source.data { val := j, isLt := h₂ }

tactic: rwa [List.getD_eq_get?, List.get?_eq_get, Option.getD_some] at this
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : ¬i < Array.size source
j : Nat
h₁ : j < List.length (List.map (fun x => AssocList.nil) source.data)
h₂ : j < List.length source.data
this : AssocList.nil = List.getD source.data j AssocList.nil
⊢ AssocList.nil = List.get source.data { val := j, isLt := h₂ }

tactic: simp
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : ¬i < Array.size source
⊢ Nat.sum (List.map (fun x => List.length (AssocList.toList x)) (List.map (fun x => AssocList.nil) source.data)) = 0

tactic: induction source.data <;> simp [*]
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : ¬i < Array.size source
⊢ Nat.sum (List.map ((fun x => List.length (AssocList.toList x)) ∘ fun x => AssocList.nil) source.data) = 0

tactic: simp
state_before: α : Type u_1
β : Type u_2
sz : Nat
inst✝ : Hashable α
buckets : Bucket α β
i : Nat
source : Array (AssocList α β)
target : Bucket α β
hs : ∀ (j : Nat), j < i → List.getD source.data j AssocList.nil = AssocList.nil
H : ¬i < Array.size source
⊢ List.length (List.map (fun x => AssocList.nil) source.data) = List.length source.data