Theorem: Array.zipWith_eq_zipWith_data
File: .lake/packages/batteries/Batteries/Data/Array/Lemmas.lean

Proof steps:
state_before: α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → γ
as : Array α
bs : Array β
⊢ ∀ (i : Nat) (cs : Array γ),
    i ≤ as.size →
      i ≤ bs.size →
        (zipWithAux f as bs i cs).data = cs.data ++ List.zipWith f (List.drop i as.data) (List.drop i bs.data)
state_after: α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → γ
as : Array α
bs : Array β
i : Nat
cs : Array γ
hia : i ≤ as.size
hib : i ≤ bs.size
⊢ (zipWithAux f as bs i cs).data = cs.data ++ List.zipWith f (List.drop i as.data) (List.drop i bs.data)
tactic: intro i cs hia hib
state_before: α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → γ
as : Array α
bs : Array β
i : Nat
cs : Array γ
hia : i ≤ as.size
hib : i ≤ bs.size
⊢ (zipWithAux f as bs i cs).data = cs.data ++ List.zipWith f (List.drop i as.data) (List.drop i bs.data)
state_after: α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → γ
as : Array α
bs : Array β
i : Nat
cs : Array γ
hia : i ≤ as.size
hib : i ≤ bs.size
⊢ (if h : i < as.size then
        let a := as[i];
        if h : i < bs.size then
          let b := bs[i];
          zipWithAux f as bs (i + 1) (cs.push (f a b))
        else cs
      else cs).data =
    cs.data ++ List.zipWith f (List.drop i as.data) (List.drop i bs.data)
tactic: unfold zipWithAux
state_before: α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → γ
as : Array α
bs : Array β
i : Nat
cs : Array γ
hia : i ≤ as.size
hib : i ≤ bs.size
⊢ (if h : i < as.size then
        let a := as[i];
        if h : i < bs.size then
          let b := bs[i];
          zipWithAux f as bs (i + 1) (cs.push (f a b))
        else cs
      else cs).data =
    cs.data ++ List.zipWith f (List.drop i as.data) (List.drop i bs.data)
state_after: case pos
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → γ
as : Array α
bs : Array β
i : Nat
cs : Array γ
hia : i ≤ as.size
hib : i ≤ bs.size
h : i = as.size ∨ i = bs.size
⊢ (if h : i < as.size then
        let a := as[i];
        if h : i < bs.size then
          let b := bs[i];
          zipWithAux f as bs (i + 1) (cs.push (f a b))
        else cs
      else cs).data =
    cs.data ++ List.zipWith f (List.drop i as.data) (List.drop i bs.data)

case neg
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → γ
as : Array α
bs : Array β
i : Nat
cs : Array γ
hia : i ≤ as.size
hib : i ≤ bs.size
h : ¬(i = as.size ∨ i = bs.size)
⊢ (if h : i < as.size then
        let a := as[i];
        if h : i < bs.size then
          let b := bs[i];
          zipWithAux f as bs (i + 1) (cs.push (f a b))
        else cs
      else cs).data =
    cs.data ++ List.zipWith f (List.drop i as.data) (List.drop i bs.data)
tactic: by_cases h : i = as.size ∨ i = bs.size
state_before: case neg
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → γ
as : Array α
bs : Array β
i : Nat
cs : Array γ
hia : i ≤ as.size
hib : i ≤ bs.size
h : ¬(i = as.size ∨ i = bs.size)
⊢ (if h : i < as.size then
        let a := as[i];
        if h : i < bs.size then
          let b := bs[i];
          zipWithAux f as bs (i + 1) (cs.push (f a b))
        else cs
      else cs).data =
    cs.data ++ List.zipWith f (List.drop i as.data) (List.drop i bs.data)
state_after: no goals
tactic: case neg =>
      rw [not_or] at h
      have has : i < as.size := Nat.lt_of_le_of_ne hia h.1
      have hbs : i < bs.size := Nat.lt_of_le_of_ne hib h.2
      simp only [has, hbs, dite_true]
      rw [loop (i+1) _ has hbs, Array.push_data]
      have h₁ : [f as[i] bs[i]] = List.zipWith f [as[i]] [bs[i]] := rfl
      let i_as : Fin as.data.length := ⟨i, has⟩
      let i_bs : Fin bs.data.length := ⟨i, hbs⟩
      rw [h₁, List.append_assoc]
      congr
      rw [← List.zipWith_append (h := by simp), getElem_eq_data_getElem, getElem_eq_data_getElem]
      show List.zipWith f (as.data[i_as] :: List.drop (i_as + 1) as.data)
        ((List.get bs.data i_bs) :: List.drop (i_bs + 1) bs.data) =
        List.zipWith f (List.drop i as.data) (List.drop i bs.data)
      simp only [data_length, Fin.getElem_fin, List.getElem_cons_drop, List.get_eq_getElem]
state_before: α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → γ
as : Array α
bs : Array β
⊢ (as.zipWith bs f).data = List.zipWith f as.data bs.data
state_after: no goals
tactic: simp [zipWith, loop 0 #[] (by simp) (by simp)]