l3lab/ntp-mathlib huggingface dataset:
theorem suffixLevenshtein_cons₁_aux {x y : {r : List δ // 0 < r.length}}
    (w₀ : x.1[0]'x.2 = y.1[0]'y.2) (w : x.1.tail = y.1.tail) : x = y := by
  match x, y with
  | ⟨hx :: tx, _⟩, ⟨hy :: ty, _⟩ => 

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x y : { r // 0 < List.length r }
hx : δ
tx : List δ
property✝¹ : 0 < List.length (hx :: tx)
hy : δ
ty : List δ
property✝ : 0 < List.length (hy :: ty)
w₀ : (↑{ val := hx :: tx, property := property✝¹ })[0] = (↑{ val := hy :: ty, property := property✝ })[0]
w : List.tail ↑{ val := hx :: tx, property := property✝¹ } = List.tail ↑{ val := hy :: ty, property := property✝ }
⊢ { val := hx :: tx, property := property✝¹ } = { val := hy :: ty, property := property✝ }

Next tactic:
simp_all
theorem suffixLevenshtein_cons₁
    (x : α) (xs ys) :
    suffixLevenshtein C (x :: xs) ys =
      ⟨levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1, by 

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
ys : List β
⊢ 0 < List.length (levenshtein C (x :: xs) ys :: ↑(suffixLevenshtein C xs ys))

Next tactic:
simp
theorem suffixLevenshtein_cons₁
    (x : α) (xs ys) :
    suffixLevenshtein C (x :: xs) ys =
      ⟨levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1, by simp⟩ := by
  

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
ys : List β
⊢ suffixLevenshtein C (x :: xs) ys =
    { val := levenshtein C (x :: xs) ys :: ↑(suffixLevenshtein C xs ys),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs ys))) }

Next tactic:
induction ys
theorem suffixLevenshtein_cons₁
    (x : α) (xs ys) :
    suffixLevenshtein C (x :: xs) ys =
      ⟨levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1, by simp⟩ := by
  induction ys
  · 

Proof state:
case nil
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
⊢ suffixLevenshtein C (x :: xs) [] =
    { val := levenshtein C (x :: xs) [] :: ↑(suffixLevenshtein C xs []),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs []))) }

Next tactic:
case nil =>
    dsimp [levenshtein, suffixLevenshtein]
theorem suffixLevenshtein_cons₁
    (x : α) (xs ys) :
    suffixLevenshtein C (x :: xs) ys =
      ⟨levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1, by simp⟩ := by
  induction ys
  · 

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
⊢ suffixLevenshtein C (x :: xs) [] =
    { val := levenshtein C (x :: xs) [] :: ↑(suffixLevenshtein C xs []),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs []))) }

Next tactic:
case nil =>
    dsimp [levenshtein, suffixLevenshtein]
theorem suffixLevenshtein_cons₁
    (x : α) (xs ys) :
    suffixLevenshtein C (x :: xs) ys =
      ⟨levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1, by simp⟩ := by
  induction ys
  · case nil =>
    

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
⊢ suffixLevenshtein C (x :: xs) [] =
    { val := levenshtein C (x :: xs) [] :: ↑(suffixLevenshtein C xs []),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs []))) }

Next tactic:
dsimp [levenshtein, suffixLevenshtein]
theorem suffixLevenshtein_cons₁
    (x : α) (xs ys) :
    suffixLevenshtein C (x :: xs) ys =
      ⟨levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1, by simp⟩ := by
  induction ys
  · case nil =>
    dsimp [levenshtein, suffixLevenshtein]
  · 

Proof state:
case cons
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
head✝ : β
tail✝ : List β
tail_ih✝ :
  suffixLevenshtein C (x :: xs) tail✝ =
    { val := levenshtein C (x :: xs) tail✝ :: ↑(suffixLevenshtein C xs tail✝),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs tail✝))) }
⊢ suffixLevenshtein C (x :: xs) (head✝ :: tail✝) =
    { val := levenshtein C (x :: xs) (head✝ :: tail✝) :: ↑(suffixLevenshtein C xs (head✝ :: tail✝)),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs (head✝ :: tail✝)))) }

Next tactic:
case cons y ys ih =>
    apply suffixLevenshtein_cons₁_aux
    · rfl
    · rw [suffixLevenshtein_cons₂ (x :: xs), ih, impl_cons]
      · rfl
      · simp [suffixLevenshtein_length]
theorem suffixLevenshtein_cons₁
    (x : α) (xs ys) :
    suffixLevenshtein C (x :: xs) ys =
      ⟨levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1, by simp⟩ := by
  induction ys
  · case nil =>
    dsimp [levenshtein, suffixLevenshtein]
  · 

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
ih :
  suffixLevenshtein C (x :: xs) ys =
    { val := levenshtein C (x :: xs) ys :: ↑(suffixLevenshtein C xs ys),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs ys))) }
⊢ suffixLevenshtein C (x :: xs) (y :: ys) =
    { val := levenshtein C (x :: xs) (y :: ys) :: ↑(suffixLevenshtein C xs (y :: ys)),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs (y :: ys)))) }

Next tactic:
case cons y ys ih =>
    apply suffixLevenshtein_cons₁_aux
    · rfl
    · rw [suffixLevenshtein_cons₂ (x :: xs), ih, impl_cons]
      · rfl
      · simp [suffixLevenshtein_length]
theorem suffixLevenshtein_cons₁
    (x : α) (xs ys) :
    suffixLevenshtein C (x :: xs) ys =
      ⟨levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1, by simp⟩ := by
  induction ys
  · case nil =>
    dsimp [levenshtein, suffixLevenshtein]
  · case cons y ys ih =>
    

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
ih :
  suffixLevenshtein C (x :: xs) ys =
    { val := levenshtein C (x :: xs) ys :: ↑(suffixLevenshtein C xs ys),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs ys))) }
⊢ suffixLevenshtein C (x :: xs) (y :: ys) =
    { val := levenshtein C (x :: xs) (y :: ys) :: ↑(suffixLevenshtein C xs (y :: ys)),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs (y :: ys)))) }

Next tactic:
apply suffixLevenshtein_cons₁_aux
theorem suffixLevenshtein_cons₁
    (x : α) (xs ys) :
    suffixLevenshtein C (x :: xs) ys =
      ⟨levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1, by simp⟩ := by
  induction ys
  · case nil =>
    dsimp [levenshtein, suffixLevenshtein]
  · case cons y ys ih =>
    apply suffixLevenshtein_cons₁_aux
    · 

Proof state:
case w₀
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
ih :
  suffixLevenshtein C (x :: xs) ys =
    { val := levenshtein C (x :: xs) ys :: ↑(suffixLevenshtein C xs ys),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs ys))) }
⊢ (↑(suffixLevenshtein C (x :: xs) (y :: ys)))[0] =
    (↑{ val := levenshtein C (x :: xs) (y :: ys) :: ↑(suffixLevenshtein C xs (y :: ys)),
          property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs (y :: ys)))) })[0]

Next tactic:
rfl
theorem suffixLevenshtein_cons₁
    (x : α) (xs ys) :
    suffixLevenshtein C (x :: xs) ys =
      ⟨levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1, by simp⟩ := by
  induction ys
  · case nil =>
    dsimp [levenshtein, suffixLevenshtein]
  · case cons y ys ih =>
    apply suffixLevenshtein_cons₁_aux
    · rfl
    · 

Proof state:
case w
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
ih :
  suffixLevenshtein C (x :: xs) ys =
    { val := levenshtein C (x :: xs) ys :: ↑(suffixLevenshtein C xs ys),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs ys))) }
⊢ List.tail ↑(suffixLevenshtein C (x :: xs) (y :: ys)) =
    List.tail
      ↑{ val := levenshtein C (x :: xs) (y :: ys) :: ↑(suffixLevenshtein C xs (y :: ys)),
          property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs (y :: ys)))) }

Next tactic:
rw [suffixLevenshtein_cons₂ (x :: xs), ih, impl_cons]
theorem suffixLevenshtein_cons₁
    (x : α) (xs ys) :
    suffixLevenshtein C (x :: xs) ys =
      ⟨levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1, by simp⟩ := by
  induction ys
  · case nil =>
    dsimp [levenshtein, suffixLevenshtein]
  · case cons y ys ih =>
    apply suffixLevenshtein_cons₁_aux
    · rfl
    · rw [suffixLevenshtein_cons₂ (x :: xs), ih, impl_cons]
      · 

Proof state:
case w
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
ih :
  suffixLevenshtein C (x :: xs) ys =
    { val := levenshtein C (x :: xs) ys :: ↑(suffixLevenshtein C xs ys),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs ys))) }
⊢ List.tail
      ↑(match impl C xs y { val := ↑(suffixLevenshtein C xs ys), property := ?w.w' } with
        | { val := r, property := w } =>
          {
            val :=
              min (Cost.delete C x + r[0])
                  (min (Cost.insert C y + levenshtein C (x :: xs) ys)
                    (Cost.substitute C x y + (↑(suffixLevenshtein C xs ys))[0])) ::
                r,
            property := (_ : 0 < Nat.succ (List.length r)) }) =
    List.tail
      ↑{ val := levenshtein C (x :: xs) (y :: ys) :: ↑(suffixLevenshtein C xs (y :: ys)),
          property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs (y :: ys)))) }

Next tactic:
rfl
theorem suffixLevenshtein_cons₁
    (x : α) (xs ys) :
    suffixLevenshtein C (x :: xs) ys =
      ⟨levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1, by simp⟩ := by
  induction ys
  · case nil =>
    dsimp [levenshtein, suffixLevenshtein]
  · case cons y ys ih =>
    apply suffixLevenshtein_cons₁_aux
    · rfl
    · rw [suffixLevenshtein_cons₂ (x :: xs), ih, impl_cons]
      · rfl
      · 

Proof state:
case w.w'
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
ih :
  suffixLevenshtein C (x :: xs) ys =
    { val := levenshtein C (x :: xs) ys :: ↑(suffixLevenshtein C xs ys),
      property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs ys))) }
⊢ 0 < List.length ↑(suffixLevenshtein C xs ys)

Next tactic:
simp [suffixLevenshtein_length]
theorem suffixLevenshtein_cons₁_fst (x : α) (xs ys) :
    (suffixLevenshtein C (x :: xs) ys).1 =
      levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1 := by
  

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
ys : List β
⊢ ↑(suffixLevenshtein C (x :: xs) ys) = levenshtein C (x :: xs) ys :: ↑(suffixLevenshtein C xs ys)

Next tactic:
simp [suffixLevenshtein_cons₁]
theorem suffixLevenshtein_cons_cons_fst_get_zero
    (x : α) (xs y ys) (w) :
    (suffixLevenshtein C (x :: xs) (y :: ys)).1[0] =
      let ⟨dx, _⟩ := suffixLevenshtein C xs (y :: ys)
      let ⟨dy, _⟩ := suffixLevenshtein C (x :: xs) ys
      let ⟨dxy, _⟩ := suffixLevenshtein C xs ys
      min
        (C.delete x + dx[0])
        (min
          (C.insert y + dy[0])
          (C.substitute x y + dxy[0])) := by
  

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
w : 0 < List.length ↑(suffixLevenshtein C (x :: xs) (y :: ys))
⊢ (↑(suffixLevenshtein C (x :: xs) (y :: ys)))[0] =
    match suffixLevenshtein C xs (y :: ys) with
    | { val := dx, property := property } =>
      match suffixLevenshtein C (x :: xs) ys with
      | { val := dy, property := property_1 } =>
        match suffixLevenshtein C xs ys with
        | { val := dxy, property := property_2 } =>
          min (Cost.delete C x + dx[0]) (min (Cost.insert C y + dy[0]) (Cost.substitute C x y + dxy[0]))

Next tactic:
conv =>
    lhs
    dsimp only [suffixLevenshtein_cons₂]
theorem suffixLevenshtein_cons_cons_fst_get_zero
    (x : α) (xs y ys) (w) :
    (suffixLevenshtein C (x :: xs) (y :: ys)).1[0] =
      let ⟨dx, _⟩ := suffixLevenshtein C xs (y :: ys)
      let ⟨dy, _⟩ := suffixLevenshtein C (x :: xs) ys
      let ⟨dxy, _⟩ := suffixLevenshtein C xs ys
      min
        (C.delete x + dx[0])
        (min
          (C.insert y + dy[0])
          (C.substitute x y + dxy[0])) := by
  conv =>
    

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
w : 0 < List.length ↑(suffixLevenshtein C (x :: xs) (y :: ys))
| (↑(suffixLevenshtein C (x :: xs) (y :: ys)))[0] =
    match suffixLevenshtein C xs (y :: ys) with
    | { val := dx, property := property } =>
      match suffixLevenshtein C (x :: xs) ys with
      | { val := dy, property := property_1 } =>
        match suffixLevenshtein C xs ys with
        | { val := dxy, property := property_2 } =>
          min (Cost.delete C x + dx[0]) (min (Cost.insert C y + dy[0]) (Cost.substitute C x y + dxy[0]))

Next tactic:
lhs
    dsimp only [suffixLevenshtein_cons₂]
theorem suffixLevenshtein_cons_cons_fst_get_zero
    (x : α) (xs y ys) (w) :
    (suffixLevenshtein C (x :: xs) (y :: ys)).1[0] =
      let ⟨dx, _⟩ := suffixLevenshtein C xs (y :: ys)
      let ⟨dy, _⟩ := suffixLevenshtein C (x :: xs) ys
      let ⟨dxy, _⟩ := suffixLevenshtein C xs ys
      min
        (C.delete x + dx[0])
        (min
          (C.insert y + dy[0])
          (C.substitute x y + dxy[0])) := by
  conv =>
    

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
w : 0 < List.length ↑(suffixLevenshtein C (x :: xs) (y :: ys))
| (↑(suffixLevenshtein C (x :: xs) (y :: ys)))[0] =
    match suffixLevenshtein C xs (y :: ys) with
    | { val := dx, property := property } =>
      match suffixLevenshtein C (x :: xs) ys with
      | { val := dy, property := property_1 } =>
        match suffixLevenshtein C xs ys with
        | { val := dxy, property := property_2 } =>
          min (Cost.delete C x + dx[0]) (min (Cost.insert C y + dy[0]) (Cost.substitute C x y + dxy[0]))

Next tactic:
lhs
theorem suffixLevenshtein_cons_cons_fst_get_zero
    (x : α) (xs y ys) (w) :
    (suffixLevenshtein C (x :: xs) (y :: ys)).1[0] =
      let ⟨dx, _⟩ := suffixLevenshtein C xs (y :: ys)
      let ⟨dy, _⟩ := suffixLevenshtein C (x :: xs) ys
      let ⟨dxy, _⟩ := suffixLevenshtein C xs ys
      min
        (C.delete x + dx[0])
        (min
          (C.insert y + dy[0])
          (C.substitute x y + dxy[0])) := by
  conv =>
    lhs
    

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
w : 0 < List.length ↑(suffixLevenshtein C (x :: xs) (y :: ys))
| (↑(suffixLevenshtein C (x :: xs) (y :: ys)))[0]

Next tactic:
dsimp only [suffixLevenshtein_cons₂]
theorem suffixLevenshtein_cons_cons_fst_get_zero
    (x : α) (xs y ys) (w) :
    (suffixLevenshtein C (x :: xs) (y :: ys)).1[0] =
      let ⟨dx, _⟩ := suffixLevenshtein C xs (y :: ys)
      let ⟨dy, _⟩ := suffixLevenshtein C (x :: xs) ys
      let ⟨dxy, _⟩ := suffixLevenshtein C xs ys
      min
        (C.delete x + dx[0])
        (min
          (C.insert y + dy[0])
          (C.substitute x y + dxy[0])) := by
  conv =>
    lhs
    dsimp only [suffixLevenshtein_cons₂]
  

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
w : 0 < List.length ↑(suffixLevenshtein C (x :: xs) (y :: ys))
⊢ (↑(impl C (x :: xs) y (suffixLevenshtein C (x :: xs) ys)))[0] =
    match suffixLevenshtein C xs (y :: ys) with
    | { val := dx, property := property } =>
      match suffixLevenshtein C (x :: xs) ys with
      | { val := dy, property := property_1 } =>
        match suffixLevenshtein C xs ys with
        | { val := dxy, property := property_2 } =>
          min (Cost.delete C x + dx[0]) (min (Cost.insert C y + dy[0]) (Cost.substitute C x y + dxy[0]))

Next tactic:
simp only [suffixLevenshtein_cons₁]
theorem suffixLevenshtein_cons_cons_fst_get_zero
    (x : α) (xs y ys) (w) :
    (suffixLevenshtein C (x :: xs) (y :: ys)).1[0] =
      let ⟨dx, _⟩ := suffixLevenshtein C xs (y :: ys)
      let ⟨dy, _⟩ := suffixLevenshtein C (x :: xs) ys
      let ⟨dxy, _⟩ := suffixLevenshtein C xs ys
      min
        (C.delete x + dx[0])
        (min
          (C.insert y + dy[0])
          (C.substitute x y + dxy[0])) := by
  conv =>
    lhs
    dsimp only [suffixLevenshtein_cons₂]
  simp only [suffixLevenshtein_cons₁]
  

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
w : 0 < List.length ↑(suffixLevenshtein C (x :: xs) (y :: ys))
⊢ (↑(impl C (x :: xs) y
          { val := levenshtein C (x :: xs) ys :: ↑(suffixLevenshtein C xs ys),
            property := (_ : 0 < Nat.succ (List.length ↑(suffixLevenshtein C xs ys))) }))[0] =
    min (Cost.delete C x + (↑(suffixLevenshtein C xs (y :: ys)))[0])
      (min (Cost.insert C y + (levenshtein C (x :: xs) ys :: ↑(suffixLevenshtein C xs ys))[0])
        (Cost.substitute C x y + (↑(suffixLevenshtein C xs ys))[0]))

Next tactic:
rw [impl_cons_fst_zero]
theorem suffixLevenshtein_cons_cons_fst_get_zero
    (x : α) (xs y ys) (w) :
    (suffixLevenshtein C (x :: xs) (y :: ys)).1[0] =
      let ⟨dx, _⟩ := suffixLevenshtein C xs (y :: ys)
      let ⟨dy, _⟩ := suffixLevenshtein C (x :: xs) ys
      let ⟨dxy, _⟩ := suffixLevenshtein C xs ys
      min
        (C.delete x + dx[0])
        (min
          (C.insert y + dy[0])
          (C.substitute x y + dxy[0])) := by
  conv =>
    lhs
    dsimp only [suffixLevenshtein_cons₂]
  simp only [suffixLevenshtein_cons₁]
  rw [impl_cons_fst_zero]
  

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
w : 0 < List.length ↑(suffixLevenshtein C (x :: xs) (y :: ys))
⊢ (match impl C xs y { val := ↑(suffixLevenshtein C xs ys), property := ?w' } with
    | { val := r, property := w } =>
      min (Cost.delete C x + r[0])
        (min (Cost.insert C y + levenshtein C (x :: xs) ys)
          (Cost.substitute C x y + (↑(suffixLevenshtein C xs ys))[0]))) =
    min (Cost.delete C x + (↑(suffixLevenshtein C xs (y :: ys)))[0])
      (min (Cost.insert C y + (levenshtein C (x :: xs) ys :: ↑(suffixLevenshtein C xs ys))[0])
        (Cost.substitute C x y + (↑(suffixLevenshtein C xs ys))[0]))
case w'
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
x : α
xs : List α
y : β
ys : List β
w : 0 < List.length ↑(suffixLevenshtein C (x :: xs) (y :: ys))
⊢ 0 < List.length ↑(suffixLevenshtein C xs ys)

Next tactic:
rfl
theorem suffixLevenshtein_eq_tails_map (xs ys) :
    (suffixLevenshtein C xs ys).1 = xs.tails.map fun xs' => levenshtein C xs' ys := by
  

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
xs : List α
ys : List β
⊢ ↑(suffixLevenshtein C xs ys) = List.map (fun xs' => levenshtein C xs' ys) (List.tails xs)

Next tactic:
induction xs
theorem suffixLevenshtein_eq_tails_map (xs ys) :
    (suffixLevenshtein C xs ys).1 = xs.tails.map fun xs' => levenshtein C xs' ys := by
  induction xs
  · 

Proof state:
case nil
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
ys : List β
⊢ ↑(suffixLevenshtein C [] ys) = List.map (fun xs' => levenshtein C xs' ys) (List.tails [])

Next tactic:
case nil =>
    simp only [List.map, suffixLevenshtein_nil']
theorem suffixLevenshtein_eq_tails_map (xs ys) :
    (suffixLevenshtein C xs ys).1 = xs.tails.map fun xs' => levenshtein C xs' ys := by
  induction xs
  · 

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
ys : List β
⊢ ↑(suffixLevenshtein C [] ys) = List.map (fun xs' => levenshtein C xs' ys) (List.tails [])

Next tactic:
case nil =>
    simp only [List.map, suffixLevenshtein_nil']
theorem suffixLevenshtein_eq_tails_map (xs ys) :
    (suffixLevenshtein C xs ys).1 = xs.tails.map fun xs' => levenshtein C xs' ys := by
  induction xs
  · case nil =>
    

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
ys : List β
⊢ ↑(suffixLevenshtein C [] ys) = List.map (fun xs' => levenshtein C xs' ys) (List.tails [])

Next tactic:
simp only [List.map, suffixLevenshtein_nil']
theorem suffixLevenshtein_eq_tails_map (xs ys) :
    (suffixLevenshtein C xs ys).1 = xs.tails.map fun xs' => levenshtein C xs' ys := by
  induction xs
  · case nil =>
    simp only [List.map, suffixLevenshtein_nil']
  · 

Proof state:
case cons
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
ys : List β
head✝ : α
tail✝ : List α
tail_ih✝ : ↑(suffixLevenshtein C tail✝ ys) = List.map (fun xs' => levenshtein C xs' ys) (List.tails tail✝)
⊢ ↑(suffixLevenshtein C (head✝ :: tail✝) ys) = List.map (fun xs' => levenshtein C xs' ys) (List.tails (head✝ :: tail✝))

Next tactic:
case cons x xs ih =>
    simp only [List.map, suffixLevenshtein_cons₁, ih]
theorem suffixLevenshtein_eq_tails_map (xs ys) :
    (suffixLevenshtein C xs ys).1 = xs.tails.map fun xs' => levenshtein C xs' ys := by
  induction xs
  · case nil =>
    simp only [List.map, suffixLevenshtein_nil']
  · 

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
ys : List β
x : α
xs : List α
ih : ↑(suffixLevenshtein C xs ys) = List.map (fun xs' => levenshtein C xs' ys) (List.tails xs)
⊢ ↑(suffixLevenshtein C (x :: xs) ys) = List.map (fun xs' => levenshtein C xs' ys) (List.tails (x :: xs))

Next tactic:
case cons x xs ih =>
    simp only [List.map, suffixLevenshtein_cons₁, ih]
theorem suffixLevenshtein_eq_tails_map (xs ys) :
    (suffixLevenshtein C xs ys).1 = xs.tails.map fun xs' => levenshtein C xs' ys := by
  induction xs
  · case nil =>
    simp only [List.map, suffixLevenshtein_nil']
  · case cons x xs ih =>
    

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
ys : List β
x : α
xs : List α
ih : ↑(suffixLevenshtein C xs ys) = List.map (fun xs' => levenshtein C xs' ys) (List.tails xs)
⊢ ↑(suffixLevenshtein C (x :: xs) ys) = List.map (fun xs' => levenshtein C xs' ys) (List.tails (x :: xs))

Next tactic:
simp only [List.map, suffixLevenshtein_cons₁, ih]
@[simp]
theorem levenshtein_nil_nil : levenshtein C [] [] = 0 := by
  

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
⊢ levenshtein C [] [] = 0

Next tactic:
simp [levenshtein, suffixLevenshtein]
@[simp]
theorem levenshtein_nil_cons (y) (ys) :
    levenshtein C [] (y :: ys) = C.insert y + levenshtein C [] ys := by
  

Proof state:
α : Type u_1
β : Type u_2
δ : Type u_3
inst✝¹ : AddZeroClass δ
inst✝ : Min δ
C : Cost α β δ
y : β
ys : List β
⊢ levenshtein C [] (y :: ys) = Cost.insert C y + levenshtein C [] ys

Next tactic:
dsimp (config := { unfoldPartialApp := true }) [levenshtein, suffixLevenshtein, impl]