l3lab/ntp-mathlib huggingface dataset:
theorem drop_sizeOf_le [SizeOf α] (l : List α) : ∀ n : ℕ, sizeOf (l.drop n) ≤ sizeOf l := by
  induction' l with _ _ lih <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : SizeOf α
⊢ ∀ (n : ℕ), sizeOf (drop n []) ≤ sizeOf []

Next tactic:
intro n
theorem drop_sizeOf_le [SizeOf α] (l : List α) : ∀ n : ℕ, sizeOf (l.drop n) ≤ sizeOf l := by
  induction' l with _ _ lih <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : SizeOf α
head✝ : α
tail✝ : List α
lih : ∀ (n : ℕ), sizeOf (drop n tail✝) ≤ sizeOf tail✝
⊢ ∀ (n : ℕ), sizeOf (drop n (head✝ :: tail✝)) ≤ sizeOf (head✝ :: tail✝)

Next tactic:
intro n
theorem drop_sizeOf_le [SizeOf α] (l : List α) : ∀ n : ℕ, sizeOf (l.drop n) ≤ sizeOf l := by
  induction' l with _ _ lih <;> intro n
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : SizeOf α
n : ℕ
⊢ sizeOf (drop n []) ≤ sizeOf []

Next tactic:
rw [drop_nil]
theorem drop_sizeOf_le [SizeOf α] (l : List α) : ∀ n : ℕ, sizeOf (l.drop n) ≤ sizeOf l := by
  induction' l with _ _ lih <;> intro n
  · rw [drop_nil]
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : SizeOf α
head✝ : α
tail✝ : List α
lih : ∀ (n : ℕ), sizeOf (drop n tail✝) ≤ sizeOf tail✝
n : ℕ
⊢ sizeOf (drop n (head✝ :: tail✝)) ≤ sizeOf (head✝ :: tail✝)

Next tactic:
induction' n with n
theorem drop_sizeOf_le [SizeOf α] (l : List α) : ∀ n : ℕ, sizeOf (l.drop n) ≤ sizeOf l := by
  induction' l with _ _ lih <;> intro n
  · rw [drop_nil]
  · induction' n with n
    · 

Proof state:
case cons.zero
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : SizeOf α
head✝ : α
tail✝ : List α
lih : ∀ (n : ℕ), sizeOf (drop n tail✝) ≤ sizeOf tail✝
⊢ sizeOf (drop zero (head✝ :: tail✝)) ≤ sizeOf (head✝ :: tail✝)

Next tactic:
rfl
theorem drop_sizeOf_le [SizeOf α] (l : List α) : ∀ n : ℕ, sizeOf (l.drop n) ≤ sizeOf l := by
  induction' l with _ _ lih <;> intro n
  · rw [drop_nil]
  · induction' n with n
    · rfl
    · 

Proof state:
case cons.succ
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
inst✝ : SizeOf α
head✝ : α
tail✝ : List α
lih : ∀ (n : ℕ), sizeOf (drop n tail✝) ≤ sizeOf tail✝
n : ℕ
n_ih✝ : sizeOf (drop n (head✝ :: tail✝)) ≤ sizeOf (head✝ :: tail✝)
⊢ sizeOf (drop (succ n) (head✝ :: tail✝)) ≤ sizeOf (head✝ :: tail✝)

Next tactic:
exact Trans.trans (lih _) le_add_self
set_option linter.deprecated false in -- FIXME
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the big list to the small list. -/
theorem get_drop (L : List α) {i j : ℕ} (h : i + j < L.length) :
    get L ⟨i + j, h⟩ = get (L.drop i) ⟨j, by
      

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
h : i + j < length L
⊢ j < length (drop i L)

Next tactic:
have A : i < L.length := lt_of_le_of_lt (Nat.le.intro rfl) h
set_option linter.deprecated false in -- FIXME
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the big list to the small list. -/
theorem get_drop (L : List α) {i j : ℕ} (h : i + j < L.length) :
    get L ⟨i + j, h⟩ = get (L.drop i) ⟨j, by
      have A : i < L.length := lt_of_le_of_lt (Nat.le.intro rfl) h
      

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
h : i + j < length L
A : i < length L
⊢ j < length (drop i L)

Next tactic:
rw [(take_append_drop i L).symm] at h
set_option linter.deprecated false in -- FIXME
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the big list to the small list. -/
theorem get_drop (L : List α) {i j : ℕ} (h : i + j < L.length) :
    get L ⟨i + j, h⟩ = get (L.drop i) ⟨j, by
      have A : i < L.length := lt_of_le_of_lt (Nat.le.intro rfl) h
      rw [(take_append_drop i L).symm] at h
      

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
h : i + j < length (take i L ++ drop i L)
A : i < length L
⊢ j < length (drop i L)

Next tactic:
simpa only [le_of_lt A, min_eq_left, add_lt_add_iff_left, length_take,
        length_append] using h
set_option linter.deprecated false in -- FIXME
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the big list to the small list. -/
theorem get_drop (L : List α) {i j : ℕ} (h : i + j < L.length) :
    get L ⟨i + j, h⟩ = get (L.drop i) ⟨j, by
      have A : i < L.length := lt_of_le_of_lt (Nat.le.intro rfl) h
      rw [(take_append_drop i L).symm] at h
      simpa only [le_of_lt A, min_eq_left, add_lt_add_iff_left, length_take,
        length_append] using h⟩ := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
h : i + j < length L
⊢ get L { val := i + j, isLt := h } = get (drop i L) { val := j, isLt := (_ : j < length (drop i L)) }

Next tactic:
rw [← nthLe_eq, ← nthLe_eq]
set_option linter.deprecated false in -- FIXME
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the big list to the small list. -/
theorem get_drop (L : List α) {i j : ℕ} (h : i + j < L.length) :
    get L ⟨i + j, h⟩ = get (L.drop i) ⟨j, by
      have A : i < L.length := lt_of_le_of_lt (Nat.le.intro rfl) h
      rw [(take_append_drop i L).symm] at h
      simpa only [le_of_lt A, min_eq_left, add_lt_add_iff_left, length_take,
        length_append] using h⟩ := by
  rw [← nthLe_eq, ← nthLe_eq]
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
h : i + j < length L
⊢ nthLe L (i + j) h = nthLe (drop i L) j (_ : j < length (drop i L))

Next tactic:
rw [nthLe_of_eq (take_append_drop i L).symm h, nthLe_append_right]
set_option linter.deprecated false in -- FIXME
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the big list to the small list. -/
theorem get_drop (L : List α) {i j : ℕ} (h : i + j < L.length) :
    get L ⟨i + j, h⟩ = get (L.drop i) ⟨j, by
      have A : i < L.length := lt_of_le_of_lt (Nat.le.intro rfl) h
      rw [(take_append_drop i L).symm] at h
      simpa only [le_of_lt A, min_eq_left, add_lt_add_iff_left, length_take,
        length_append] using h⟩ := by
  rw [← nthLe_eq, ← nthLe_eq]
  rw [nthLe_of_eq (take_append_drop i L).symm h, nthLe_append_right] <;>
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
h : i + j < length L
⊢ nthLe (drop i L) (i + j - length (take i L)) (_ : i + j - length (take i L) < length (drop i L)) =
    nthLe (drop i L) j (_ : j < length (drop i L))

Next tactic:
simp [min_eq_left (show i ≤ length L from le_trans (by simp) (le_of_lt h))]
set_option linter.deprecated false in -- FIXME
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the big list to the small list. -/
theorem get_drop (L : List α) {i j : ℕ} (h : i + j < L.length) :
    get L ⟨i + j, h⟩ = get (L.drop i) ⟨j, by
      have A : i < L.length := lt_of_le_of_lt (Nat.le.intro rfl) h
      rw [(take_append_drop i L).symm] at h
      simpa only [le_of_lt A, min_eq_left, add_lt_add_iff_left, length_take,
        length_append] using h⟩ := by
  rw [← nthLe_eq, ← nthLe_eq]
  rw [nthLe_of_eq (take_append_drop i L).symm h, nthLe_append_right] <;>
  simp [min_eq_left (show i ≤ length L from le_trans (by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
h : i + j < length L
⊢ i ≤ i + j

Next tactic:
simp
set_option linter.deprecated false in -- FIXME
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the big list to the small list. -/
theorem get_drop (L : List α) {i j : ℕ} (h : i + j < L.length) :
    get L ⟨i + j, h⟩ = get (L.drop i) ⟨j, by
      have A : i < L.length := lt_of_le_of_lt (Nat.le.intro rfl) h
      rw [(take_append_drop i L).symm] at h
      simpa only [le_of_lt A, min_eq_left, add_lt_add_iff_left, length_take,
        length_append] using h⟩ := by
  rw [← nthLe_eq, ← nthLe_eq]
  rw [nthLe_of_eq (take_append_drop i L).symm h, nthLe_append_right] <;>
  

Proof state:
case h₁
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
h : i + j < length L
⊢ length (take i L) ≤ i + j

Next tactic:
simp [min_eq_left (show i ≤ length L from le_trans (by simp) (le_of_lt h))]
set_option linter.deprecated false in
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the big list to the small list. -/
@[deprecated get_drop]
theorem nthLe_drop (L : List α) {i j : ℕ} (h : i + j < L.length) :
    nthLe L (i + j) h = nthLe (L.drop i) j (by
      

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
h : i + j < length L
⊢ j < length (drop i L)

Next tactic:
have A : i < L.length := lt_of_le_of_lt (Nat.le.intro rfl) h
set_option linter.deprecated false in
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the big list to the small list. -/
@[deprecated get_drop]
theorem nthLe_drop (L : List α) {i j : ℕ} (h : i + j < L.length) :
    nthLe L (i + j) h = nthLe (L.drop i) j (by
      have A : i < L.length := lt_of_le_of_lt (Nat.le.intro rfl) h
      

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
h : i + j < length L
A : i < length L
⊢ j < length (drop i L)

Next tactic:
rw [(take_append_drop i L).symm] at h
set_option linter.deprecated false in
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the big list to the small list. -/
@[deprecated get_drop]
theorem nthLe_drop (L : List α) {i j : ℕ} (h : i + j < L.length) :
    nthLe L (i + j) h = nthLe (L.drop i) j (by
      have A : i < L.length := lt_of_le_of_lt (Nat.le.intro rfl) h
      rw [(take_append_drop i L).symm] at h
      

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
h : i + j < length (take i L ++ drop i L)
A : i < length L
⊢ j < length (drop i L)

Next tactic:
simpa only [le_of_lt A, min_eq_left, add_lt_add_iff_left, length_take,
        length_append] using h
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
dropping the first `i` elements. Version designed to rewrite from the small list to the big list. -/
theorem get_drop' (L : List α) {i j} :
    get (L.drop i) j = get L ⟨i + j, lt_tsub_iff_left.mp (length_drop i L ▸ j.2)⟩ := by
  

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

Next tactic:
rw [get_drop]
theorem get?_drop (L : List α) (i j : ℕ) : get? (L.drop i) j = get? L (i + j) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
⊢ get? (drop i L) j = get? L (i + j)

Next tactic:
ext
theorem get?_drop (L : List α) (i j : ℕ) : get? (L.drop i) j = get? L (i + j) := by
  ext
  

Proof state:
case a
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
a✝ : α
⊢ a✝ ∈ get? (drop i L) j ↔ a✝ ∈ get? L (i + j)

Next tactic:
simp only [get?_eq_some, get_drop', Option.mem_def]
theorem get?_drop (L : List α) (i j : ℕ) : get? (L.drop i) j = get? L (i + j) := by
  ext
  simp only [get?_eq_some, get_drop', Option.mem_def]
  

Proof state:
case a
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
a✝ : α
⊢ (∃ h, get L { val := i + j, isLt := (_ : i + ↑{ val := j, isLt := (_ : j < length (drop i L)) } < length L) } = a✝) ↔
    ∃ h, get L { val := i + j, isLt := h } = a✝

Next tactic:
constructor
theorem get?_drop (L : List α) (i j : ℕ) : get? (L.drop i) j = get? L (i + j) := by
  ext
  simp only [get?_eq_some, get_drop', Option.mem_def]
  constructor <;> 

Proof state:
case a.mp
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
a✝ : α
⊢ (∃ h, get L { val := i + j, isLt := (_ : i + ↑{ val := j, isLt := (_ : j < length (drop i L)) } < length L) } = a✝) →
    ∃ h, get L { val := i + j, isLt := h } = a✝

Next tactic:
exact fun ⟨h, ha⟩ => ⟨by simpa [lt_tsub_iff_left] using h, ha⟩
theorem get?_drop (L : List α) (i j : ℕ) : get? (L.drop i) j = get? L (i + j) := by
  ext
  simp only [get?_eq_some, get_drop', Option.mem_def]
  constructor <;> exact fun ⟨h, ha⟩ => ⟨by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
a✝ : α
x✝ : ∃ h, get L { val := i + j, isLt := (_ : i + ↑{ val := j, isLt := (_ : j < length (drop i L)) } < length L) } = a✝
h : j < length (drop i L)
ha : get L { val := i + j, isLt := (_ : i + ↑{ val := j, isLt := (_ : j < length (drop i L)) } < length L) } = a✝
⊢ i + j < length L

Next tactic:
simpa [lt_tsub_iff_left] using h
theorem get?_drop (L : List α) (i j : ℕ) : get? (L.drop i) j = get? L (i + j) := by
  ext
  simp only [get?_eq_some, get_drop', Option.mem_def]
  constructor <;> 

Proof state:
case a.mpr
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
a✝ : α
⊢ (∃ h, get L { val := i + j, isLt := h } = a✝) →
    ∃ h, get L { val := i + j, isLt := (_ : i + ↑{ val := j, isLt := (_ : j < length (drop i L)) } < length L) } = a✝

Next tactic:
exact fun ⟨h, ha⟩ => ⟨by simpa [lt_tsub_iff_left] using h, ha⟩
theorem get?_drop (L : List α) (i j : ℕ) : get? (L.drop i) j = get? L (i + j) := by
  ext
  simp only [get?_eq_some, get_drop', Option.mem_def]
  constructor <;> exact fun ⟨h, ha⟩ => ⟨by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i j : ℕ
a✝ : α
x✝ : ∃ h, get L { val := i + j, isLt := h } = a✝
h : i + j < length L
ha : get L { val := i + j, isLt := h } = a✝
⊢ j < length (drop i L)

Next tactic:
simpa [lt_tsub_iff_left] using h
@[simp]
theorem drop_drop (n : ℕ) : ∀ (m) (l : List α), drop n (drop m l) = drop (n + m) l
  | m, [] => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n m : ℕ
⊢ drop n (drop m []) = drop (n + m) []

Next tactic:
simp
@[simp]
theorem drop_drop (n : ℕ) : ∀ (m) (l : List α), drop n (drop m l) = drop (n + m) l
  | m, [] => by simp
  | 0, l => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
l : List α
⊢ drop n (drop 0 l) = drop (n + 0) l

Next tactic:
simp
theorem drop_take : ∀ (m : ℕ) (n : ℕ) (l : List α), drop m (take (m + n) l) = take n (drop m l)
  | 0, n, _ => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
x✝ : List α
⊢ drop 0 (take (0 + n) x✝) = take n (drop 0 x✝)

Next tactic:
simp
theorem drop_take : ∀ (m : ℕ) (n : ℕ) (l : List α), drop m (take (m + n) l) = take n (drop m l)
  | 0, n, _ => by simp
  | m + 1, n, nil => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
m n : ℕ
⊢ drop (m + 1) (take (m + 1 + n) []) = take n (drop (m + 1) [])

Next tactic:
simp
theorem drop_take : ∀ (m : ℕ) (n : ℕ) (l : List α), drop m (take (m + n) l) = take n (drop m l)
  | 0, n, _ => by simp
  | m + 1, n, nil => by simp
  | m + 1, n, _ :: l => by
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
m n : ℕ
head✝ : α
l : List α
⊢ drop (m + 1) (take (m + 1 + n) (head✝ :: l)) = take n (drop (m + 1) (head✝ :: l))

Next tactic:
have h : m + 1 + n = m + n + 1 := by ac_rfl
theorem drop_take : ∀ (m : ℕ) (n : ℕ) (l : List α), drop m (take (m + n) l) = take n (drop m l)
  | 0, n, _ => by simp
  | m + 1, n, nil => by simp
  | m + 1, n, _ :: l => by
    have h : m + 1 + n = m + n + 1 := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
m n : ℕ
head✝ : α
l : List α
⊢ m + 1 + n = m + n + 1

Next tactic:
ac_rfl
theorem drop_take : ∀ (m : ℕ) (n : ℕ) (l : List α), drop m (take (m + n) l) = take n (drop m l)
  | 0, n, _ => by simp
  | m + 1, n, nil => by simp
  | m + 1, n, _ :: l => by
    have h : m + 1 + n = m + n + 1 := by ac_rfl
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
m n : ℕ
head✝ : α
l : List α
h : m + 1 + n = m + n + 1
⊢ drop (m + 1) (take (m + 1 + n) (head✝ :: l)) = take n (drop (m + 1) (head✝ :: l))

Next tactic:
simpa [take_cons, h] using drop_take m n l
theorem map_drop {α β : Type*} (f : α → β) :
    ∀ (L : List α) (i : ℕ), (L.drop i).map f = (L.map f).drop i
  | [], i => by 

Proof state:
ι : Type u_1
α✝ : Type u
β✝ : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u_2
β : Type u_3
f : α → β
i : ℕ
⊢ map f (drop i []) = drop i (map f [])

Next tactic:
simp
theorem map_drop {α β : Type*} (f : α → β) :
    ∀ (L : List α) (i : ℕ), (L.drop i).map f = (L.map f).drop i
  | [], i => by simp
  | L, 0 => by 

Proof state:
ι : Type u_1
α✝ : Type u
β✝ : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u_2
β : Type u_3
f : α → β
L : List α
⊢ map f (drop 0 L) = drop 0 (map f L)

Next tactic:
simp
theorem map_drop {α β : Type*} (f : α → β) :
    ∀ (L : List α) (i : ℕ), (L.drop i).map f = (L.map f).drop i
  | [], i => by simp
  | L, 0 => by simp
  | h :: t, n + 1 => by
    

Proof state:
ι : Type u_1
α✝ : Type u
β✝ : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u_2
β : Type u_3
f : α → β
h : α
t : List α
n : ℕ
⊢ map f (drop (n + 1) (h :: t)) = drop (n + 1) (map f (h :: t))

Next tactic:
dsimp
theorem map_drop {α β : Type*} (f : α → β) :
    ∀ (L : List α) (i : ℕ), (L.drop i).map f = (L.map f).drop i
  | [], i => by simp
  | L, 0 => by simp
  | h :: t, n + 1 => by
    dsimp
    

Proof state:
ι : Type u_1
α✝ : Type u
β✝ : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u_2
β : Type u_3
f : α → β
h : α
t : List α
n : ℕ
⊢ map f (drop n t) = drop n (map f t)

Next tactic:
rw [map_drop f t]
theorem modifyNth_eq_take_cons_drop (f : α → α) {n l} (h) :
    modifyNth f n l = take n l ++ f (get l ⟨n, h⟩) :: drop (n + 1) l := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → α
n : ℕ
l : List α
h : n < length l
⊢ modifyNth f n l = take n l ++ f (get l { val := n, isLt := h }) :: drop (n + 1) l

Next tactic:
rw [modifyNth_eq_take_drop, drop_eq_get_cons h]
theorem modifyNth_eq_take_cons_drop (f : α → α) {n l} (h) :
    modifyNth f n l = take n l ++ f (get l ⟨n, h⟩) :: drop (n + 1) l := by
  rw [modifyNth_eq_take_drop, drop_eq_get_cons h]; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → α
n : ℕ
l : List α
h : n < length l
⊢ take n l ++ modifyHead f (get l { val := n, isLt := h } :: drop (n + 1) l) =
    take n l ++ f (get l { val := n, isLt := h }) :: drop (n + 1) l

Next tactic:
rfl
theorem set_eq_take_cons_drop (a : α) {n l} (h : n < length l) :
    set l n a = take n l ++ a :: drop (n + 1) l := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
n : ℕ
l : List α
h : n < length l
⊢ set l n a = take n l ++ a :: drop (n + 1) l

Next tactic:
rw [set_eq_modifyNth, modifyNth_eq_take_cons_drop _ h]
theorem reverse_take {α} {xs : List α} (n : ℕ) (h : n ≤ xs.length) :
    xs.reverse.take n = (xs.drop (xs.length - n)).reverse := by
  

Proof state:
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u_2
xs : List α
n : ℕ
h : n ≤ length xs
⊢ take n (reverse xs) = reverse (drop (length xs - n) xs)

Next tactic:
induction' xs with xs_hd xs_tl xs_ih generalizing n
theorem reverse_take {α} {xs : List α} (n : ℕ) (h : n ≤ xs.length) :
    xs.reverse.take n = (xs.drop (xs.length - n)).reverse := by
  induction' xs with xs_hd xs_tl xs_ih generalizing n <;>
    

Proof state:
case nil
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u_2
n : ℕ
h : n ≤ length []
⊢ take n (reverse []) = reverse (drop (length [] - n) [])

Next tactic:
simp only [reverse_cons, drop, reverse_nil, zero_tsub, length, take_nil]
theorem reverse_take {α} {xs : List α} (n : ℕ) (h : n ≤ xs.length) :
    xs.reverse.take n = (xs.drop (xs.length - n)).reverse := by
  induction' xs with xs_hd xs_tl xs_ih generalizing n <;>
    

Proof state:
case cons
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u_2
xs_hd : α
xs_tl : List α
xs_ih : ∀ (n : ℕ), n ≤ length xs_tl → take n (reverse xs_tl) = reverse (drop (length xs_tl - n) xs_tl)
n : ℕ
h : n ≤ length (xs_hd :: xs_tl)
⊢ take n (reverse (xs_hd :: xs_tl)) = reverse (drop (length (xs_hd :: xs_tl) - n) (xs_hd :: xs_tl))

Next tactic:
simp only [reverse_cons, drop, reverse_nil, zero_tsub, length, take_nil]
theorem reverse_take {α} {xs : List α} (n : ℕ) (h : n ≤ xs.length) :
    xs.reverse.take n = (xs.drop (xs.length - n)).reverse := by
  induction' xs with xs_hd xs_tl xs_ih generalizing n <;>
    simp only [reverse_cons, drop, reverse_nil, zero_tsub, length, take_nil]
  

Proof state:
case cons
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u_2
xs_hd : α
xs_tl : List α
xs_ih : ∀ (n : ℕ), n ≤ length xs_tl → take n (reverse xs_tl) = reverse (drop (length xs_tl - n) xs_tl)
n : ℕ
h : n ≤ length (xs_hd :: xs_tl)
⊢ take n (reverse xs_tl ++ [xs_hd]) = reverse (drop (length xs_tl + 1 - n) (xs_hd :: xs_tl))

Next tactic:
cases' h.lt_or_eq_dec with h' h'
theorem reverse_take {α} {xs : List α} (n : ℕ) (h : n ≤ xs.length) :
    xs.reverse.take n = (xs.drop (xs.length - n)).reverse := by
  induction' xs with xs_hd xs_tl xs_ih generalizing n <;>
    simp only [reverse_cons, drop, reverse_nil, zero_tsub, length, take_nil]
  cases' h.lt_or_eq_dec with h' h'
  · 

Proof state:
case cons.inl
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u_2
xs_hd : α
xs_tl : List α
xs_ih : ∀ (n : ℕ), n ≤ length xs_tl → take n (reverse xs_tl) = reverse (drop (length xs_tl - n) xs_tl)
n : ℕ
h : n ≤ length (xs_hd :: xs_tl)
h' : n < length (xs_hd :: xs_tl)
⊢ take n (reverse xs_tl ++ [xs_hd]) = reverse (drop (length xs_tl + 1 - n) (xs_hd :: xs_tl))

Next tactic:
replace h' := le_of_succ_le_succ h'
theorem reverse_take {α} {xs : List α} (n : ℕ) (h : n ≤ xs.length) :
    xs.reverse.take n = (xs.drop (xs.length - n)).reverse := by
  induction' xs with xs_hd xs_tl xs_ih generalizing n <;>
    simp only [reverse_cons, drop, reverse_nil, zero_tsub, length, take_nil]
  cases' h.lt_or_eq_dec with h' h'
  · replace h' := le_of_succ_le_succ h'
    

Proof state:
case cons.inl
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u_2
xs_hd : α
xs_tl : List α
xs_ih : ∀ (n : ℕ), n ≤ length xs_tl → take n (reverse xs_tl) = reverse (drop (length xs_tl - n) xs_tl)
n : ℕ
h : n ≤ length (xs_hd :: xs_tl)
h' : n ≤ length xs_tl
⊢ take n (reverse xs_tl ++ [xs_hd]) = reverse (drop (length xs_tl + 1 - n) (xs_hd :: xs_tl))

Next tactic:
rw [take_append_of_le_length, xs_ih _ h']
theorem reverse_take {α} {xs : List α} (n : ℕ) (h : n ≤ xs.length) :
    xs.reverse.take n = (xs.drop (xs.length - n)).reverse := by
  induction' xs with xs_hd xs_tl xs_ih generalizing n <;>
    simp only [reverse_cons, drop, reverse_nil, zero_tsub, length, take_nil]
  cases' h.lt_or_eq_dec with h' h'
  · replace h' := le_of_succ_le_succ h'
    rw [take_append_of_le_length, xs_ih _ h']
    

Proof state:
case cons.inl
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u_2
xs_hd : α
xs_tl : List α
xs_ih : ∀ (n : ℕ), n ≤ length xs_tl → take n (reverse xs_tl) = reverse (drop (length xs_tl - n) xs_tl)
n : ℕ
h : n ≤ length (xs_hd :: xs_tl)
h' : n ≤ length xs_tl
⊢ reverse (drop (length xs_tl - n) xs_tl) = reverse (drop (length xs_tl + 1 - n) (xs_hd :: xs_tl))
case cons.inl
ι : Type u_1
α✝ : Type u
β : Type v
γ : Type w
l₁ l₂ : List α✝
α : Type u_2
xs_hd : α
xs_tl : List α
xs_ih : ∀ (n : ℕ), n ≤ length xs_tl → take n (reverse xs_tl) = reverse (drop (length xs_tl - n) xs_tl)
n : ℕ
h : n ≤ length (xs_hd :: xs_tl)
h' : n ≤ length xs_tl
⊢ n ≤ length (reverse xs_tl)

Next tactic:
rw [show xs_tl.length + 1 - n = succ (xs_tl.length - n) from _, drop]