l3lab/ntp-mathlib huggingface dataset:
theorem erase_diff_erase_sublist_of_sublist {a : α} :
    ∀ {l₁ l₂ : List α}, l₁ <+ l₂ → (l₂.erase a).diff (l₁.erase a) <+ l₂.diff l₁
  | [], l₂, _ => erase_sublist _ _
  | b :: l₁, l₂, h =>
    if heq : b = a then by simp only [heq, erase_cons_head, diff_cons]; rfl
    else by
      simp only [erase_cons_head b l₁, erase_cons_tail l₁ heq,
        diff_cons ((List.erase l₂ a)) (List.erase l₁ a) b, diff_cons l₂ l₁ b, erase_comm a b l₂]
      

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
a b : α
l₁ l₂ : List α
h : b :: l₁ <+ l₂
heq : ¬b = a
⊢ List.diff (List.erase (List.erase l₂ b) a) (List.erase l₁ a) <+ List.diff (List.erase l₂ b) l₁

Next tactic:
have h' := h.erase b
theorem erase_diff_erase_sublist_of_sublist {a : α} :
    ∀ {l₁ l₂ : List α}, l₁ <+ l₂ → (l₂.erase a).diff (l₁.erase a) <+ l₂.diff l₁
  | [], l₂, _ => erase_sublist _ _
  | b :: l₁, l₂, h =>
    if heq : b = a then by simp only [heq, erase_cons_head, diff_cons]; rfl
    else by
      simp only [erase_cons_head b l₁, erase_cons_tail l₁ heq,
        diff_cons ((List.erase l₂ a)) (List.erase l₁ a) b, diff_cons l₂ l₁ b, erase_comm a b l₂]
      have h' := h.erase b
      

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
a b : α
l₁ l₂ : List α
h : b :: l₁ <+ l₂
heq : ¬b = a
h' : List.erase (b :: l₁) b <+ List.erase l₂ b
⊢ List.diff (List.erase (List.erase l₂ b) a) (List.erase l₁ a) <+ List.diff (List.erase l₂ b) l₁

Next tactic:
rw [erase_cons_head] at h'
theorem erase_diff_erase_sublist_of_sublist {a : α} :
    ∀ {l₁ l₂ : List α}, l₁ <+ l₂ → (l₂.erase a).diff (l₁.erase a) <+ l₂.diff l₁
  | [], l₂, _ => erase_sublist _ _
  | b :: l₁, l₂, h =>
    if heq : b = a then by simp only [heq, erase_cons_head, diff_cons]; rfl
    else by
      simp only [erase_cons_head b l₁, erase_cons_tail l₁ heq,
        diff_cons ((List.erase l₂ a)) (List.erase l₁ a) b, diff_cons l₂ l₁ b, erase_comm a b l₂]
      have h' := h.erase b
      rw [erase_cons_head] at h'
      

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁✝ l₂✝ : List α
inst✝ : DecidableEq α
a b : α
l₁ l₂ : List α
h : b :: l₁ <+ l₂
heq : ¬b = a
h' : l₁ <+ List.erase l₂ b
⊢ List.diff (List.erase (List.erase l₂ b) a) (List.erase l₁ a) <+ List.diff (List.erase l₂ b) l₁

Next tactic:
exact @erase_diff_erase_sublist_of_sublist _ l₁ (l₂.erase b) h'
@[simp]
theorem enumFrom_get? :
    ∀ (n) (l : List α) (m), get? (enumFrom n l) m = (fun a => (n + m, a)) <$> get? l m
  | n, [], m => rfl
  | n, a :: l, 0 => rfl
  | n, a :: l, m + 1 => (enumFrom_get? (n + 1) l m).trans <| by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
a : α
l : List α
m : ℕ
⊢ (fun a => (n + 1 + m, a)) <$> get? l m = (fun a => (n + (m + 1), a)) <$> get? (a :: l) (m + 1)

Next tactic:
rw [add_right_comm]
@[simp]
theorem enumFrom_get? :
    ∀ (n) (l : List α) (m), get? (enumFrom n l) m = (fun a => (n + m, a)) <$> get? l m
  | n, [], m => rfl
  | n, a :: l, 0 => rfl
  | n, a :: l, m + 1 => (enumFrom_get? (n + 1) l m).trans <| by rw [add_right_comm]; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
a : α
l : List α
m : ℕ
⊢ (fun a => (n + m + 1, a)) <$> get? l m = (fun a => (n + (m + 1), a)) <$> get? (a :: l) (m + 1)

Next tactic:
rfl
@[simp]
theorem enum_get? : ∀ (l : List α) (n), get? (enum l) n = (fun a => (n, a)) <$> get? l n := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
⊢ ∀ (l : List α) (n : ℕ), get? (enum l) n = (fun a => (n, a)) <$> get? l n

Next tactic:
simp only [enum, enumFrom_get?, zero_add]
@[simp]
theorem enum_get? : ∀ (l : List α) (n), get? (enum l) n = (fun a => (n, a)) <$> get? l n := by
  simp only [enum, enumFrom_get?, zero_add]; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
⊢ List α → ℕ → True

Next tactic:
intros
@[simp]
theorem enum_get? : ∀ (l : List α) (n), get? (enum l) n = (fun a => (n, a)) <$> get? l n := by
  simp only [enum, enumFrom_get?, zero_add]; intros; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l✝ : List α
n✝ : ℕ
⊢ True

Next tactic:
trivial
theorem mem_enumFrom {x : α} {i : ℕ} :
    ∀ {j : ℕ} (xs : List α), (i, x) ∈ xs.enumFrom j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
  | j, [] => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
i j : ℕ
⊢ (i, x) ∈ enumFrom j [] → j ≤ i ∧ i < j + length [] ∧ x ∈ []

Next tactic:
simp [enumFrom]
theorem mem_enumFrom {x : α} {i : ℕ} :
    ∀ {j : ℕ} (xs : List α), (i, x) ∈ xs.enumFrom j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
  | j, [] => by simp [enumFrom]
  | j, y :: ys => by
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
i j : ℕ
y : α
ys : List α
⊢ (i, x) ∈ enumFrom j (y :: ys) → j ≤ i ∧ i < j + length (y :: ys) ∧ x ∈ y :: ys

Next tactic:
suffices
      i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys →
        j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)
      by simpa [enumFrom, mem_enumFrom ys]
theorem mem_enumFrom {x : α} {i : ℕ} :
    ∀ {j : ℕ} (xs : List α), (i, x) ∈ xs.enumFrom j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
  | j, [] => by simp [enumFrom]
  | j, y :: ys => by
    suffices
      i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys →
        j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)
      by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
i j : ℕ
y : α
ys : List α
this : i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys → j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)
⊢ (i, x) ∈ enumFrom j (y :: ys) → j ≤ i ∧ i < j + length (y :: ys) ∧ x ∈ y :: ys

Next tactic:
simpa [enumFrom, mem_enumFrom ys]
theorem mem_enumFrom {x : α} {i : ℕ} :
    ∀ {j : ℕ} (xs : List α), (i, x) ∈ xs.enumFrom j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
  | j, [] => by simp [enumFrom]
  | j, y :: ys => by
    suffices
      i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys →
        j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)
      by simpa [enumFrom, mem_enumFrom ys]
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
i j : ℕ
y : α
ys : List α
⊢ i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys → j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)

Next tactic:
rintro (h | h)
theorem mem_enumFrom {x : α} {i : ℕ} :
    ∀ {j : ℕ} (xs : List α), (i, x) ∈ xs.enumFrom j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
  | j, [] => by simp [enumFrom]
  | j, y :: ys => by
    suffices
      i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys →
        j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)
      by simpa [enumFrom, mem_enumFrom ys]
    rintro (h | h)
    · 

Proof state:
case inl
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
i j : ℕ
y : α
ys : List α
h : i = j ∧ x = y
⊢ j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)

Next tactic:
refine' ⟨le_of_eq h.1.symm, h.1 ▸ _, Or.inl h.2⟩
theorem mem_enumFrom {x : α} {i : ℕ} :
    ∀ {j : ℕ} (xs : List α), (i, x) ∈ xs.enumFrom j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
  | j, [] => by simp [enumFrom]
  | j, y :: ys => by
    suffices
      i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys →
        j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)
      by simpa [enumFrom, mem_enumFrom ys]
    rintro (h | h)
    · refine' ⟨le_of_eq h.1.symm, h.1 ▸ _, Or.inl h.2⟩
      

Proof state:
case inl
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
i j : ℕ
y : α
ys : List α
h : i = j ∧ x = y
⊢ i < i + (length ys + 1)

Next tactic:
apply Nat.lt_add_of_pos_right
theorem mem_enumFrom {x : α} {i : ℕ} :
    ∀ {j : ℕ} (xs : List α), (i, x) ∈ xs.enumFrom j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
  | j, [] => by simp [enumFrom]
  | j, y :: ys => by
    suffices
      i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys →
        j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)
      by simpa [enumFrom, mem_enumFrom ys]
    rintro (h | h)
    · refine' ⟨le_of_eq h.1.symm, h.1 ▸ _, Or.inl h.2⟩
      apply Nat.lt_add_of_pos_right; 

Proof state:
case inl.h
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
i j : ℕ
y : α
ys : List α
h : i = j ∧ x = y
⊢ 0 < length ys + 1

Next tactic:
simp
theorem mem_enumFrom {x : α} {i : ℕ} :
    ∀ {j : ℕ} (xs : List α), (i, x) ∈ xs.enumFrom j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
  | j, [] => by simp [enumFrom]
  | j, y :: ys => by
    suffices
      i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys →
        j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)
      by simpa [enumFrom, mem_enumFrom ys]
    rintro (h | h)
    · refine' ⟨le_of_eq h.1.symm, h.1 ▸ _, Or.inl h.2⟩
      apply Nat.lt_add_of_pos_right; simp
    · 

Proof state:
case inr
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
i j : ℕ
y : α
ys : List α
h : (i, x) ∈ enumFrom (j + 1) ys
⊢ j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)

Next tactic:
have ⟨hji, hijlen, hmem⟩ := mem_enumFrom _ h
theorem mem_enumFrom {x : α} {i : ℕ} :
    ∀ {j : ℕ} (xs : List α), (i, x) ∈ xs.enumFrom j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
  | j, [] => by simp [enumFrom]
  | j, y :: ys => by
    suffices
      i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys →
        j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)
      by simpa [enumFrom, mem_enumFrom ys]
    rintro (h | h)
    · refine' ⟨le_of_eq h.1.symm, h.1 ▸ _, Or.inl h.2⟩
      apply Nat.lt_add_of_pos_right; simp
    · have ⟨hji, hijlen, hmem⟩ := mem_enumFrom _ h
      

Proof state:
case inr
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
i j : ℕ
y : α
ys : List α
h : (i, x) ∈ enumFrom (j + 1) ys
hji : j + 1 ≤ i
hijlen : i < j + 1 + length ys
hmem : x ∈ ys
⊢ j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)

Next tactic:
refine' ⟨_, _, _⟩
theorem mem_enumFrom {x : α} {i : ℕ} :
    ∀ {j : ℕ} (xs : List α), (i, x) ∈ xs.enumFrom j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
  | j, [] => by simp [enumFrom]
  | j, y :: ys => by
    suffices
      i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys →
        j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)
      by simpa [enumFrom, mem_enumFrom ys]
    rintro (h | h)
    · refine' ⟨le_of_eq h.1.symm, h.1 ▸ _, Or.inl h.2⟩
      apply Nat.lt_add_of_pos_right; simp
    · have ⟨hji, hijlen, hmem⟩ := mem_enumFrom _ h
      refine' ⟨_, _, _⟩
      · 

Proof state:
case inr.refine'_1
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
i j : ℕ
y : α
ys : List α
h : (i, x) ∈ enumFrom (j + 1) ys
hji : j + 1 ≤ i
hijlen : i < j + 1 + length ys
hmem : x ∈ ys
⊢ j ≤ i

Next tactic:
exact le_trans (Nat.le_succ _) hji
theorem mem_enumFrom {x : α} {i : ℕ} :
    ∀ {j : ℕ} (xs : List α), (i, x) ∈ xs.enumFrom j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
  | j, [] => by simp [enumFrom]
  | j, y :: ys => by
    suffices
      i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys →
        j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)
      by simpa [enumFrom, mem_enumFrom ys]
    rintro (h | h)
    · refine' ⟨le_of_eq h.1.symm, h.1 ▸ _, Or.inl h.2⟩
      apply Nat.lt_add_of_pos_right; simp
    · have ⟨hji, hijlen, hmem⟩ := mem_enumFrom _ h
      refine' ⟨_, _, _⟩
      · exact le_trans (Nat.le_succ _) hji
      · 

Proof state:
case inr.refine'_2
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
i j : ℕ
y : α
ys : List α
h : (i, x) ∈ enumFrom (j + 1) ys
hji : j + 1 ≤ i
hijlen : i < j + 1 + length ys
hmem : x ∈ ys
⊢ i < j + (length ys + 1)

Next tactic:
convert hijlen using 1
theorem mem_enumFrom {x : α} {i : ℕ} :
    ∀ {j : ℕ} (xs : List α), (i, x) ∈ xs.enumFrom j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
  | j, [] => by simp [enumFrom]
  | j, y :: ys => by
    suffices
      i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys →
        j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)
      by simpa [enumFrom, mem_enumFrom ys]
    rintro (h | h)
    · refine' ⟨le_of_eq h.1.symm, h.1 ▸ _, Or.inl h.2⟩
      apply Nat.lt_add_of_pos_right; simp
    · have ⟨hji, hijlen, hmem⟩ := mem_enumFrom _ h
      refine' ⟨_, _, _⟩
      · exact le_trans (Nat.le_succ _) hji
      · convert hijlen using 1
        

Proof state:
case h.e'_4
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
i j : ℕ
y : α
ys : List α
h : (i, x) ∈ enumFrom (j + 1) ys
hji : j + 1 ≤ i
hijlen : i < j + 1 + length ys
hmem : x ∈ ys
⊢ j + (length ys + 1) = j + 1 + length ys

Next tactic:
ac_rfl
theorem mem_enumFrom {x : α} {i : ℕ} :
    ∀ {j : ℕ} (xs : List α), (i, x) ∈ xs.enumFrom j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
  | j, [] => by simp [enumFrom]
  | j, y :: ys => by
    suffices
      i = j ∧ x = y ∨ (i, x) ∈ enumFrom (j + 1) ys →
        j ≤ i ∧ i < j + (length ys + 1) ∧ (x = y ∨ x ∈ ys)
      by simpa [enumFrom, mem_enumFrom ys]
    rintro (h | h)
    · refine' ⟨le_of_eq h.1.symm, h.1 ▸ _, Or.inl h.2⟩
      apply Nat.lt_add_of_pos_right; simp
    · have ⟨hji, hijlen, hmem⟩ := mem_enumFrom _ h
      refine' ⟨_, _, _⟩
      · exact le_trans (Nat.le_succ _) hji
      · convert hijlen using 1
        ac_rfl
      · 

Proof state:
case inr.refine'_3
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
i j : ℕ
y : α
ys : List α
h : (i, x) ∈ enumFrom (j + 1) ys
hji : j + 1 ≤ i
hijlen : i < j + 1 + length ys
hmem : x ∈ ys
⊢ x = y ∨ x ∈ ys

Next tactic:
simp [hmem]
theorem enumFrom_append (xs ys : List α) (n : ℕ) :
    enumFrom n (xs ++ ys) = enumFrom n xs ++ enumFrom (n + xs.length) ys := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ xs ys : List α
n : ℕ
⊢ enumFrom n (xs ++ ys) = enumFrom n xs ++ enumFrom (n + length xs) ys

Next tactic:
induction' xs with x xs IH generalizing ys n
theorem enumFrom_append (xs ys : List α) (n : ℕ) :
    enumFrom n (xs ++ ys) = enumFrom n xs ++ enumFrom (n + xs.length) ys := by
  induction' xs with x xs IH generalizing ys n
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ ys : List α
n : ℕ
⊢ enumFrom n ([] ++ ys) = enumFrom n [] ++ enumFrom (n + length []) ys

Next tactic:
simp
theorem enumFrom_append (xs ys : List α) (n : ℕ) :
    enumFrom n (xs ++ ys) = enumFrom n xs ++ enumFrom (n + xs.length) ys := by
  induction' xs with x xs IH generalizing ys n
  · simp
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
xs : List α
IH : ∀ (ys : List α) (n : ℕ), enumFrom n (xs ++ ys) = enumFrom n xs ++ enumFrom (n + length xs) ys
ys : List α
n : ℕ
⊢ enumFrom n (x :: xs ++ ys) = enumFrom n (x :: xs) ++ enumFrom (n + length (x :: xs)) ys

Next tactic:
rw [cons_append, enumFrom_cons, IH, ← cons_append, ← enumFrom_cons, length, add_right_comm,
      add_assoc]
theorem enum_append (xs ys : List α) : enum (xs ++ ys) = enum xs ++ enumFrom xs.length ys := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ xs ys : List α
⊢ enum (xs ++ ys) = enum xs ++ enumFrom (length xs) ys

Next tactic:
simp [enum, enumFrom_append]
theorem map_fst_add_enumFrom_eq_enumFrom (l : List α) (n k : ℕ) :
    map (Prod.map (· + n) id) (enumFrom k l) = enumFrom (n + k) l := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
n k : ℕ
⊢ map (Prod.map (fun x => x + n) id) (enumFrom k l) = enumFrom (n + k) l

Next tactic:
induction' l with hd tl IH generalizing n k
theorem map_fst_add_enumFrom_eq_enumFrom (l : List α) (n k : ℕ) :
    map (Prod.map (· + n) id) (enumFrom k l) = enumFrom (n + k) l := by
  induction' l with hd tl IH generalizing n k
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n k : ℕ
⊢ map (Prod.map (fun x => x + n) id) (enumFrom k []) = enumFrom (n + k) []

Next tactic:
simp [enumFrom]
theorem map_fst_add_enumFrom_eq_enumFrom (l : List α) (n k : ℕ) :
    map (Prod.map (· + n) id) (enumFrom k l) = enumFrom (n + k) l := by
  induction' l with hd tl IH generalizing n k
  · simp [enumFrom]
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
hd : α
tl : List α
IH : ∀ (n k : ℕ), map (Prod.map (fun x => x + n) id) (enumFrom k tl) = enumFrom (n + k) tl
n k : ℕ
⊢ map (Prod.map (fun x => x + n) id) (enumFrom k (hd :: tl)) = enumFrom (n + k) (hd :: tl)

Next tactic:
simp only [enumFrom, map, zero_add, Prod.map_mk, id.def, eq_self_iff_true, true_and_iff]
theorem map_fst_add_enumFrom_eq_enumFrom (l : List α) (n k : ℕ) :
    map (Prod.map (· + n) id) (enumFrom k l) = enumFrom (n + k) l := by
  induction' l with hd tl IH generalizing n k
  · simp [enumFrom]
  · simp only [enumFrom, map, zero_add, Prod.map_mk, id.def, eq_self_iff_true, true_and_iff]
    

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
hd : α
tl : List α
IH : ∀ (n k : ℕ), map (Prod.map (fun x => x + n) id) (enumFrom k tl) = enumFrom (n + k) tl
n k : ℕ
⊢ (k + n, hd) :: map (Prod.map (fun x => x + n) id) (enumFrom (k + 1) tl) = (n + k, hd) :: enumFrom (n + k + 1) tl

Next tactic:
simp [IH, add_comm n k, add_assoc, add_left_comm]
theorem enumFrom_cons' (n : ℕ) (x : α) (xs : List α) :
    enumFrom n (x :: xs) = (n, x) :: (enumFrom n xs).map (Prod.map Nat.succ id) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
x : α
xs : List α
⊢ enumFrom n (x :: xs) = (n, x) :: map (Prod.map succ id) (enumFrom n xs)

Next tactic:
rw [enumFrom_cons, add_comm, ← map_fst_add_enumFrom_eq_enumFrom]
theorem enumFrom_map (n : ℕ) (l : List α) (f : α → β) :
    enumFrom n (l.map f) = (enumFrom n l).map (Prod.map id f) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
l : List α
f : α → β
⊢ enumFrom n (map f l) = map (Prod.map id f) (enumFrom n l)

Next tactic:
induction' l with hd tl IH
theorem enumFrom_map (n : ℕ) (l : List α) (f : α → β) :
    enumFrom n (l.map f) = (enumFrom n l).map (Prod.map id f) := by
  induction' l with hd tl IH
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
f : α → β
⊢ enumFrom n (map f []) = map (Prod.map id f) (enumFrom n [])

Next tactic:
rfl
theorem enumFrom_map (n : ℕ) (l : List α) (f : α → β) :
    enumFrom n (l.map f) = (enumFrom n l).map (Prod.map id f) := by
  induction' l with hd tl IH
  · rfl
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
f : α → β
hd : α
tl : List α
IH : enumFrom n (map f tl) = map (Prod.map id f) (enumFrom n tl)
⊢ enumFrom n (map f (hd :: tl)) = map (Prod.map id f) (enumFrom n (hd :: tl))

Next tactic:
rw [map_cons, enumFrom_cons', enumFrom_cons', map_cons, map_map, IH, map_map]
theorem enumFrom_map (n : ℕ) (l : List α) (f : α → β) :
    enumFrom n (l.map f) = (enumFrom n l).map (Prod.map id f) := by
  induction' l with hd tl IH
  · rfl
  · rw [map_cons, enumFrom_cons', enumFrom_cons', map_cons, map_map, IH, map_map]
    

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
f : α → β
hd : α
tl : List α
IH : enumFrom n (map f tl) = map (Prod.map id f) (enumFrom n tl)
⊢ (n, f hd) :: map (Prod.map succ id ∘ Prod.map id f) (enumFrom n tl) =
    Prod.map id f (n, hd) :: map (Prod.map id f ∘ Prod.map succ id) (enumFrom n tl)

Next tactic:
rfl
theorem get_enumFrom (l : List α) (n) (i : Fin (l.enumFrom n).length)
    (hi : i.1 < l.length := (by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
n : ℕ
i : Fin (length (enumFrom n l))
⊢ ↑i < length l

Next tactic:
simpa using i.2
theorem get_enumFrom (l : List α) (n) (i : Fin (l.enumFrom n).length)
    (hi : i.1 < l.length := (by simpa using i.2)) :
    (l.enumFrom n).get i = (n + i, l.get ⟨i, hi⟩) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
n : ℕ
i : Fin (length (enumFrom n l))
hi : optParam (↑i < length l) (_ : ↑i < length l)
⊢ get (enumFrom n l) i = (n + ↑i, get l { val := ↑i, isLt := hi })

Next tactic:
rw [← Option.some_inj, ← get?_eq_get]
theorem get_enumFrom (l : List α) (n) (i : Fin (l.enumFrom n).length)
    (hi : i.1 < l.length := (by simpa using i.2)) :
    (l.enumFrom n).get i = (n + i, l.get ⟨i, hi⟩) := by
  rw [← Option.some_inj, ← get?_eq_get]
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
n : ℕ
i : Fin (length (enumFrom n l))
hi : optParam (↑i < length l) (_ : ↑i < length l)
⊢ get? (enumFrom n l) ↑i = some (n + ↑i, get l { val := ↑i, isLt := hi })

Next tactic:
simp [enumFrom_get?, get?_eq_get hi]
set_option linter.deprecated false in
@[deprecated get_enumFrom]
theorem nthLe_enumFrom (l : List α) (n i : ℕ) (hi' : i < (l.enumFrom n).length)
    (hi : i < l.length := (by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
n i : ℕ
hi' : i < length (enumFrom n l)
⊢ i < length l

Next tactic:
simpa using hi'
theorem get_enum (l : List α) (i : Fin l.enum.length)
    (hi : i < l.length := (by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
i : Fin (length (enum l))
⊢ ↑i < length l

Next tactic:
simpa using i.2
theorem get_enum (l : List α) (i : Fin l.enum.length)
    (hi : i < l.length := (by simpa using i.2)) :
    l.enum.get i = (i.1, l.get ⟨i, hi⟩) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
i : Fin (length (enum l))
hi : optParam (↑i < length l) (_ : ↑i < length l)
⊢ get (enum l) i = (↑i, get l { val := ↑i, isLt := hi })

Next tactic:
convert get_enumFrom _ _ i
theorem get_enum (l : List α) (i : Fin l.enum.length)
    (hi : i < l.length := (by simpa using i.2)) :
    l.enum.get i = (i.1, l.get ⟨i, hi⟩) := by
  convert get_enumFrom _ _ i
  

Proof state:
case h.e'_3.h.e'_3
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
i : Fin (length (enum l))
hi : optParam (↑i < length l) (_ : ↑i < length l)
⊢ ↑i = 0 + ↑i

Next tactic:
exact (zero_add _).symm
set_option linter.deprecated false in
@[deprecated get_enum]
theorem nthLe_enum (l : List α) (i : ℕ) (hi' : i < l.enum.length)
    (hi : i < l.length := (by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
i : ℕ
hi' : i < length (enum l)
⊢ i < length l

Next tactic:
simpa using hi'
@[simp]
theorem enumFrom_eq_nil {n : ℕ} {l : List α} : List.enumFrom n l = [] ↔ l = [] := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
l : List α
⊢ enumFrom n l = [] ↔ l = []

Next tactic:
cases l
@[simp]
theorem enumFrom_eq_nil {n : ℕ} {l : List α} : List.enumFrom n l = [] ↔ l = [] := by
  cases l <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
⊢ enumFrom n [] = [] ↔ [] = []

Next tactic:
simp
@[simp]
theorem enumFrom_eq_nil {n : ℕ} {l : List α} : List.enumFrom n l = [] ↔ l = [] := by
  cases l <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
head✝ : α
tail✝ : List α
⊢ enumFrom n (head✝ :: tail✝) = [] ↔ head✝ :: tail✝ = []

Next tactic:
simp
@[simp]
theorem map₂Left'_nil_right (f : α → Option β → γ) (as) :
    map₂Left' f as [] = (as.map fun a => f a none, []) := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
as : List α
⊢ map₂Left' f as [] = (map (fun a => f a none) as, [])

Next tactic:
cases as
@[simp]
theorem map₂Left'_nil_right (f : α → Option β → γ) (as) :
    map₂Left' f as [] = (as.map fun a => f a none, []) := by cases as <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
⊢ map₂Left' f [] [] = (map (fun a => f a none) [], [])

Next tactic:
rfl
@[simp]
theorem map₂Left'_nil_right (f : α → Option β → γ) (as) :
    map₂Left' f as [] = (as.map fun a => f a none, []) := by cases as <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
head✝ : α
tail✝ : List α
⊢ map₂Left' f (head✝ :: tail✝) [] = (map (fun a => f a none) (head✝ :: tail✝), [])

Next tactic:
rfl
@[simp]
theorem map₂Right'_nil_left : map₂Right' f [] bs = (bs.map (f none), []) := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : Option α → β → γ
a : α
as : List α
b : β
bs : List β
⊢ map₂Right' f [] bs = (map (f none) bs, [])

Next tactic:
cases bs
@[simp]
theorem map₂Right'_nil_left : map₂Right' f [] bs = (bs.map (f none), []) := by cases bs <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : Option α → β → γ
a : α
as : List α
b : β
⊢ map₂Right' f [] [] = (map (f none) [], [])

Next tactic:
rfl