l3lab/ntp-mathlib huggingface dataset:
theorem nil_zipWith (f : α → β → γ) (l : List β) : zipWith f [] l = [] := by cases l <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β → γ
head✝ : β
tail✝ : List β
⊢ zipWith f [] (head✝ :: tail✝) = []

Next tactic:
rfl
theorem zipWith_nil (f : α → β → γ) (l : List α) : zipWith f l [] = [] := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β → γ
l : List α
⊢ zipWith f l [] = []

Next tactic:
cases l
theorem zipWith_nil (f : α → β → γ) (l : List α) : zipWith f l [] = [] := by cases l <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β → γ
⊢ zipWith f [] [] = []

Next tactic:
rfl
theorem zipWith_nil (f : α → β → γ) (l : List α) : zipWith f l [] = [] := by cases l <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β → γ
head✝ : α
tail✝ : List α
⊢ zipWith f (head✝ :: tail✝) [] = []

Next tactic:
rfl
@[simp]
theorem zipWith_flip (f : α → β → γ) : ∀ as bs, zipWith (flip f) bs as = zipWith f as bs
  | [], [] => rfl
  | [], b :: bs => rfl
  | a :: as, [] => rfl
  | a :: as, b :: bs => by
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β → γ
a : α
as : List α
b : β
bs : List β
⊢ zipWith (flip f) (b :: bs) (a :: as) = zipWith f (a :: as) (b :: bs)

Next tactic:
simp! [zipWith_flip]
@[simp]
theorem zipWith_flip (f : α → β → γ) : ∀ as bs, zipWith (flip f) bs as = zipWith f as bs
  | [], [] => rfl
  | [], b :: bs => rfl
  | a :: as, [] => rfl
  | a :: as, b :: bs => by
    simp! [zipWith_flip]
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β → γ
a : α
as : List α
b : β
bs : List β
⊢ flip f b a = f a b

Next tactic:
rfl
theorem take_all_of_le : ∀ {n} {l : List α}, length l ≤ n → take n l = l
  | 0, [], _ => rfl
  | 0, a :: l, h => absurd h (not_le_of_gt (zero_lt_succ _))
  | n + 1, [], _ => rfl
  | n + 1, a :: l, h => by
    

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

Next tactic:
change a :: take n l = a :: l
theorem take_all_of_le : ∀ {n} {l : List α}, length l ≤ n → take n l = l
  | 0, [], _ => rfl
  | 0, a :: l, h => absurd h (not_le_of_gt (zero_lt_succ _))
  | n + 1, [], _ => rfl
  | n + 1, a :: l, h => by
    change a :: take n l = a :: l
    

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

Next tactic:
rw [take_all_of_le (le_of_succ_le_succ h)]
theorem take_left' {l₁ l₂ : List α} {n} (h : length l₁ = n) : take n (l₁ ++ l₂) = l₁ := by
  

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

Next tactic:
rw [← h]
theorem take_left' {l₁ l₂ : List α} {n} (h : length l₁ = n) : take n (l₁ ++ l₂) = l₁ := by
  rw [← h]; 

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

Next tactic:
apply take_left
theorem take_take : ∀ (n m) (l : List α), take n (take m l) = take (min n m) l
  | n, 0, l => by 

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

Next tactic:
rw [min_zero, take_zero, take_nil]
theorem take_take : ∀ (n m) (l : List α), take n (take m l) = take (min n m) l
  | n, 0, l => by rw [min_zero, take_zero, take_nil]
  | 0, m, l => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
m : ℕ
l : List α
⊢ take 0 (take m l) = take (min 0 m) l

Next tactic:
rw [zero_min, take_zero, take_zero]
theorem take_take : ∀ (n m) (l : List α), take n (take m l) = take (min n m) l
  | n, 0, l => by rw [min_zero, take_zero, take_nil]
  | 0, m, l => by rw [zero_min, take_zero, take_zero]
  | succ n, succ m, nil => by 

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

Next tactic:
simp only [take_nil]
theorem take_take : ∀ (n m) (l : List α), take n (take m l) = take (min n m) l
  | n, 0, l => by rw [min_zero, take_zero, take_nil]
  | 0, m, l => by rw [zero_min, take_zero, take_zero]
  | succ n, succ m, nil => by simp only [take_nil]
  | succ n, succ m, a :: l => by
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n m : ℕ
a : α
l : List α
⊢ take (succ n) (take (succ m) (a :: l)) = take (min (succ n) (succ m)) (a :: l)

Next tactic:
simp only [take, succ_min_succ, take_take n m l]
theorem take_replicate (a : α) : ∀ n m : ℕ, take n (replicate m a) = replicate (min n m) a
  | n, 0 => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
n : ℕ
⊢ take n (replicate 0 a) = replicate (min n 0) a

Next tactic:
simp
theorem take_replicate (a : α) : ∀ n m : ℕ, take n (replicate m a) = replicate (min n m) a
  | n, 0 => by simp
  | 0, m => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
m : ℕ
⊢ take 0 (replicate m a) = replicate (min 0 m) a

Next tactic:
simp
theorem take_replicate (a : α) : ∀ n m : ℕ, take n (replicate m a) = replicate (min n m) a
  | n, 0 => by simp
  | 0, m => by simp
  | succ n, succ m => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
n m : ℕ
⊢ take (succ n) (replicate (succ m) a) = replicate (min (succ n) (succ m)) a

Next tactic:
simp [succ_min_succ, take_replicate]
theorem map_take {α β : Type*} (f : α → β) :
    ∀ (L : List α) (i : ℕ), (L.take i).map f = (L.map f).take 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 (take i []) = take i (map f [])

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

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

Next tactic:
simp
theorem map_take {α β : Type*} (f : α → β) :
    ∀ (L : List α) (i : ℕ), (L.take i).map f = (L.map f).take i
  | [], i => by simp
  | _, 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 (take (n + 1) (h :: t)) = take (n + 1) (map f (h :: t))

Next tactic:
dsimp
theorem map_take {α β : Type*} (f : α → β) :
    ∀ (L : List α) (i : ℕ), (L.take i).map f = (L.map f).take i
  | [], i => by simp
  | _, 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 : ℕ
⊢ f h :: map f (take n t) = f h :: take n (map f t)

Next tactic:
rw [map_take f t n]
/-- Taking the first `n` elements in `l₁ ++ l₂` is the same as appending the first `n` elements
of `l₁` to the first `n - l₁.length` elements of `l₂`. -/
theorem take_append_eq_append_take {l₁ l₂ : List α} {n : ℕ} :
    take n (l₁ ++ l₂) = take n l₁ ++ take (n - l₁.length) l₂ := by
  

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

Next tactic:
induction l₁ generalizing n
/-- Taking the first `n` elements in `l₁ ++ l₂` is the same as appending the first `n` elements
of `l₁` to the first `n - l₁.length` elements of `l₂`. -/
theorem take_append_eq_append_take {l₁ l₂ : List α} {n : ℕ} :
    take n (l₁ ++ l₂) = take n l₁ ++ take (n - l₁.length) l₂ := by
  induction l₁ generalizing n; 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂✝ l₂ : List α
n : ℕ
⊢ take n ([] ++ l₂) = take n [] ++ take (n - length []) l₂
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂✝ l₂ : List α
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ {n : ℕ}, take n (tail✝ ++ l₂) = take n tail✝ ++ take (n - length tail✝) l₂
n : ℕ
⊢ take n (head✝ :: tail✝ ++ l₂) = take n (head✝ :: tail✝) ++ take (n - length (head✝ :: tail✝)) l₂

Next tactic:
{simp}
/-- Taking the first `n` elements in `l₁ ++ l₂` is the same as appending the first `n` elements
of `l₁` to the first `n - l₁.length` elements of `l₂`. -/
theorem take_append_eq_append_take {l₁ l₂ : List α} {n : ℕ} :
    take n (l₁ ++ l₂) = take n l₁ ++ take (n - l₁.length) l₂ := by
  induction l₁ generalizing n; {

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

Next tactic:
simp
/-- Taking the first `n` elements in `l₁ ++ l₂` is the same as appending the first `n` elements
of `l₁` to the first `n - l₁.length` elements of `l₂`. -/
theorem take_append_eq_append_take {l₁ l₂ : List α} {n : ℕ} :
    take n (l₁ ++ l₂) = take n l₁ ++ take (n - l₁.length) l₂ := by
  induction l₁ generalizing n; {simp}
  

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂✝ l₂ : List α
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ {n : ℕ}, take n (tail✝ ++ l₂) = take n tail✝ ++ take (n - length tail✝) l₂
n : ℕ
⊢ take n (head✝ :: tail✝ ++ l₂) = take n (head✝ :: tail✝) ++ take (n - length (head✝ :: tail✝)) l₂

Next tactic:
cases n
/-- Taking the first `n` elements in `l₁ ++ l₂` is the same as appending the first `n` elements
of `l₁` to the first `n - l₁.length` elements of `l₂`. -/
theorem take_append_eq_append_take {l₁ l₂ : List α} {n : ℕ} :
    take n (l₁ ++ l₂) = take n l₁ ++ take (n - l₁.length) l₂ := by
  induction l₁ generalizing n; {simp}
  cases n <;> 

Proof state:
case cons.zero
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂✝ l₂ : List α
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ {n : ℕ}, take n (tail✝ ++ l₂) = take n tail✝ ++ take (n - length tail✝) l₂
⊢ take zero (head✝ :: tail✝ ++ l₂) = take zero (head✝ :: tail✝) ++ take (zero - length (head✝ :: tail✝)) l₂

Next tactic:
simp [*]
/-- Taking the first `n` elements in `l₁ ++ l₂` is the same as appending the first `n` elements
of `l₁` to the first `n - l₁.length` elements of `l₂`. -/
theorem take_append_eq_append_take {l₁ l₂ : List α} {n : ℕ} :
    take n (l₁ ++ l₂) = take n l₁ ++ take (n - l₁.length) l₂ := by
  induction l₁ generalizing n; {simp}
  cases n <;> 

Proof state:
case cons.succ
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂✝ l₂ : List α
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ {n : ℕ}, take n (tail✝ ++ l₂) = take n tail✝ ++ take (n - length tail✝) l₂
n✝ : ℕ
⊢ take (succ n✝) (head✝ :: tail✝ ++ l₂) = take (succ n✝) (head✝ :: tail✝) ++ take (succ n✝ - length (head✝ :: tail✝)) l₂

Next tactic:
simp [*]
theorem take_append_of_le_length {l₁ l₂ : List α} {n : ℕ} (h : n ≤ l₁.length) :
    (l₁ ++ l₂).take n = l₁.take n := by 

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

Next tactic:
simp [take_append_eq_append_take, tsub_eq_zero_iff_le.mpr h]
/-- Taking the first `l₁.length + i` elements in `l₁ ++ l₂` is the same as appending the first
`i` elements of `l₂` to `l₁`. -/
theorem take_append {l₁ l₂ : List α} (i : ℕ) : take (l₁.length + i) (l₁ ++ l₂) = l₁ ++ take i l₂ :=
  by 

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

Next tactic:
simp [take_append_eq_append_take, take_all_of_le le_self_add]
/-- The `i`-th element of a list coincides with the `i`-th element of any of its prefixes of
length `> i`. Version designed to rewrite from the small list to the big list. -/
theorem get_take' (L : List α) {j i} :
    get (L.take j) i = get L ⟨i.1, lt_of_lt_of_le i.2 (by 

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

Next tactic:
simp [le_refl]
/-- The `i`-th element of a list coincides with the `i`-th element of any of its prefixes of
length `> i`. Version designed to rewrite from the small list to the big list. -/
theorem get_take' (L : List α) {j i} :
    get (L.take j) i = get L ⟨i.1, lt_of_lt_of_le i.2 (by simp [le_refl])⟩ := by
  

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

Next tactic:
let ⟨i, hi⟩ := i
/-- The `i`-th element of a list coincides with the `i`-th element of any of its prefixes of
length `> i`. Version designed to rewrite from the small list to the big list. -/
theorem get_take' (L : List α) {j i} :
    get (L.take j) i = get L ⟨i.1, lt_of_lt_of_le i.2 (by simp [le_refl])⟩ := by
  let ⟨i, hi⟩ := i; 

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

Next tactic:
simp at hi
/-- The `i`-th element of a list coincides with the `i`-th element of any of its prefixes of
length `> i`. Version designed to rewrite from the small list to the big list. -/
theorem get_take' (L : List α) {j i} :
    get (L.take j) i = get L ⟨i.1, lt_of_lt_of_le i.2 (by simp [le_refl])⟩ := by
  let ⟨i, hi⟩ := i; simp at hi; 

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

Next tactic:
rw [get_take L _ hi.1]
set_option linter.deprecated false in
/-- The `i`-th element of a list coincides with the `i`-th element of any of its prefixes of
length `> i`. Version designed to rewrite from the small list to the big list. -/
@[deprecated get_take']
theorem nthLe_take' (L : List α) {i j : ℕ} (hi : i < (L.take j).length) :
    nthLe (L.take j) i hi = nthLe L i (lt_of_lt_of_le hi (by 

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

Next tactic:
simp [le_refl]
theorem get?_take {l : List α} {n m : ℕ} (h : m < n) : (l.take n).get? m = l.get? m := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
n m : ℕ
h : m < n
⊢ get? (take n l) m = get? l m

Next tactic:
induction' n with n hn generalizing l m
theorem get?_take {l : List α} {n m : ℕ} (h : m < n) : (l.take n).get? m = l.get? m := by
  induction' n with n hn generalizing l m
  · 

Proof state:
case zero
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
m : ℕ
h : m < zero
⊢ get? (take zero l) m = get? l m

Next tactic:
simp only [Nat.zero_eq] at h
theorem get?_take {l : List α} {n m : ℕ} (h : m < n) : (l.take n).get? m = l.get? m := by
  induction' n with n hn generalizing l m
  · simp only [Nat.zero_eq] at h
    

Proof state:
case zero
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
m : ℕ
h : m < 0
⊢ get? (take zero l) m = get? l m

Next tactic:
exact absurd h (not_lt_of_le m.zero_le)
theorem get?_take {l : List α} {n m : ℕ} (h : m < n) : (l.take n).get? m = l.get? m := by
  induction' n with n hn generalizing l m
  · simp only [Nat.zero_eq] at h
    exact absurd h (not_lt_of_le m.zero_le)
  · 

Proof state:
case succ
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
hn : ∀ {l : List α} {m : ℕ}, m < n → get? (take n l) m = get? l m
l : List α
m : ℕ
h : m < succ n
⊢ get? (take (succ n) l) m = get? l m

Next tactic:
cases' l with hd tl
theorem get?_take {l : List α} {n m : ℕ} (h : m < n) : (l.take n).get? m = l.get? m := by
  induction' n with n hn generalizing l m
  · simp only [Nat.zero_eq] at h
    exact absurd h (not_lt_of_le m.zero_le)
  · cases' l with hd tl
    · 

Proof state:
case succ.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
hn : ∀ {l : List α} {m : ℕ}, m < n → get? (take n l) m = get? l m
m : ℕ
h : m < succ n
⊢ get? (take (succ n) []) m = get? [] m

Next tactic:
simp only [take_nil]
theorem get?_take {l : List α} {n m : ℕ} (h : m < n) : (l.take n).get? m = l.get? m := by
  induction' n with n hn generalizing l m
  · simp only [Nat.zero_eq] at h
    exact absurd h (not_lt_of_le m.zero_le)
  · cases' l with hd tl
    · simp only [take_nil]
    · 

Proof state:
case succ.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
hn : ∀ {l : List α} {m : ℕ}, m < n → get? (take n l) m = get? l m
m : ℕ
h : m < succ n
hd : α
tl : List α
⊢ get? (take (succ n) (hd :: tl)) m = get? (hd :: tl) m

Next tactic:
cases m
theorem get?_take {l : List α} {n m : ℕ} (h : m < n) : (l.take n).get? m = l.get? m := by
  induction' n with n hn generalizing l m
  · simp only [Nat.zero_eq] at h
    exact absurd h (not_lt_of_le m.zero_le)
  · cases' l with hd tl
    · simp only [take_nil]
    · cases m
      · 

Proof state:
case succ.cons.zero
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
hn : ∀ {l : List α} {m : ℕ}, m < n → get? (take n l) m = get? l m
hd : α
tl : List α
h : zero < succ n
⊢ get? (take (succ n) (hd :: tl)) zero = get? (hd :: tl) zero

Next tactic:
simp only [get?, take]
theorem get?_take {l : List α} {n m : ℕ} (h : m < n) : (l.take n).get? m = l.get? m := by
  induction' n with n hn generalizing l m
  · simp only [Nat.zero_eq] at h
    exact absurd h (not_lt_of_le m.zero_le)
  · cases' l with hd tl
    · simp only [take_nil]
    · cases m
      · simp only [get?, take]
      · 

Proof state:
case succ.cons.succ
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
hn : ∀ {l : List α} {m : ℕ}, m < n → get? (take n l) m = get? l m
hd : α
tl : List α
n✝ : ℕ
h : succ n✝ < succ n
⊢ get? (take (succ n) (hd :: tl)) (succ n✝) = get? (hd :: tl) (succ n✝)

Next tactic:
simpa only using hn (Nat.lt_of_succ_lt_succ h)
theorem take_succ {l : List α} {n : ℕ} : l.take (n + 1) = l.take n ++ (l.get? n).toList := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
n : ℕ
⊢ take (n + 1) l = take n l ++ Option.toList (get? l n)

Next tactic:
induction' l with hd tl hl generalizing n
theorem take_succ {l : List α} {n : ℕ} : l.take (n + 1) = l.take n ++ (l.get? n).toList := by
  induction' l with hd tl hl generalizing n
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n : ℕ
⊢ take (n + 1) [] = take n [] ++ Option.toList (get? [] n)

Next tactic:
simp only [Option.toList, get?, take_nil, append_nil]
theorem take_succ {l : List α} {n : ℕ} : l.take (n + 1) = l.take n ++ (l.get? n).toList := by
  induction' l with hd tl hl generalizing n
  · simp only [Option.toList, get?, take_nil, append_nil]
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
hd : α
tl : List α
hl : ∀ {n : ℕ}, take (n + 1) tl = take n tl ++ Option.toList (get? tl n)
n : ℕ
⊢ take (n + 1) (hd :: tl) = take n (hd :: tl) ++ Option.toList (get? (hd :: tl) n)

Next tactic:
cases n
theorem take_succ {l : List α} {n : ℕ} : l.take (n + 1) = l.take n ++ (l.get? n).toList := by
  induction' l with hd tl hl generalizing n
  · simp only [Option.toList, get?, take_nil, append_nil]
  · cases n
    · 

Proof state:
case cons.zero
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
hd : α
tl : List α
hl : ∀ {n : ℕ}, take (n + 1) tl = take n tl ++ Option.toList (get? tl n)
⊢ take (zero + 1) (hd :: tl) = take zero (hd :: tl) ++ Option.toList (get? (hd :: tl) zero)

Next tactic:
simp only [Option.toList, get?, eq_self_iff_true, and_self_iff, take, nil_append]
theorem take_succ {l : List α} {n : ℕ} : l.take (n + 1) = l.take n ++ (l.get? n).toList := by
  induction' l with hd tl hl generalizing n
  · simp only [Option.toList, get?, take_nil, append_nil]
  · cases n
    · simp only [Option.toList, get?, eq_self_iff_true, and_self_iff, take, nil_append]
    · 

Proof state:
case cons.succ
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
hd : α
tl : List α
hl : ∀ {n : ℕ}, take (n + 1) tl = take n tl ++ Option.toList (get? tl n)
n✝ : ℕ
⊢ take (succ n✝ + 1) (hd :: tl) = take (succ n✝) (hd :: tl) ++ Option.toList (get? (hd :: tl) (succ n✝))

Next tactic:
simp only [hl, cons_append, get?, eq_self_iff_true, and_self_iff, take]
@[simp]
theorem take_eq_nil_iff {l : List α} {k : ℕ} : l.take k = [] ↔ l = [] ∨ k = 0 := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
k : ℕ
⊢ take k l = [] ↔ l = [] ∨ k = 0

Next tactic:
cases l
@[simp]
theorem take_eq_nil_iff {l : List α} {k : ℕ} : l.take k = [] ↔ l = [] ∨ k = 0 := by
  cases l <;> 

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

Next tactic:
cases k
@[simp]
theorem take_eq_nil_iff {l : List α} {k : ℕ} : l.take k = [] ↔ l = [] ∨ k = 0 := by
  cases l <;> 

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

Next tactic:
cases k
@[simp]
theorem take_eq_nil_iff {l : List α} {k : ℕ} : l.take k = [] ↔ l = [] ∨ k = 0 := by
  cases l <;> cases k <;> 

Proof state:
case nil.zero
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
⊢ take zero [] = [] ↔ [] = [] ∨ zero = 0

Next tactic:
simp [Nat.succ_ne_zero]
@[simp]
theorem take_eq_nil_iff {l : List α} {k : ℕ} : l.take k = [] ↔ l = [] ∨ k = 0 := by
  cases l <;> cases k <;> 

Proof state:
case nil.succ
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
n✝ : ℕ
⊢ take (succ n✝) [] = [] ↔ [] = [] ∨ succ n✝ = 0

Next tactic:
simp [Nat.succ_ne_zero]
@[simp]
theorem take_eq_nil_iff {l : List α} {k : ℕ} : l.take k = [] ↔ l = [] ∨ k = 0 := by
  cases l <;> cases k <;> 

Proof state:
case cons.zero
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
head✝ : α
tail✝ : List α
⊢ take zero (head✝ :: tail✝) = [] ↔ head✝ :: tail✝ = [] ∨ zero = 0

Next tactic:
simp [Nat.succ_ne_zero]
@[simp]
theorem take_eq_nil_iff {l : List α} {k : ℕ} : l.take k = [] ↔ l = [] ∨ k = 0 := by
  cases l <;> cases k <;> 

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

Next tactic:
simp [Nat.succ_ne_zero]
theorem take_eq_take :
    ∀ {l : List α} {m n : ℕ}, l.take m = l.take n ↔ min m l.length = min n l.length
  | [], m, n => by 

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

Next tactic:
simp
theorem take_eq_take :
    ∀ {l : List α} {m n : ℕ}, l.take m = l.take n ↔ min m l.length = min n l.length
  | [], m, n => by simp
  | _ :: xs, 0, 0 => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
head✝ : α
xs : List α
⊢ take 0 (head✝ :: xs) = take 0 (head✝ :: xs) ↔ min 0 (length (head✝ :: xs)) = min 0 (length (head✝ :: xs))

Next tactic:
simp
theorem take_eq_take :
    ∀ {l : List α} {m n : ℕ}, l.take m = l.take n ↔ min m l.length = min n l.length
  | [], m, n => by simp
  | _ :: xs, 0, 0 => by simp
  | x :: xs, m + 1, 0 => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
xs : List α
m : ℕ
⊢ take (m + 1) (x :: xs) = take 0 (x :: xs) ↔ min (m + 1) (length (x :: xs)) = min 0 (length (x :: xs))

Next tactic:
simp
theorem take_eq_take :
    ∀ {l : List α} {m n : ℕ}, l.take m = l.take n ↔ min m l.length = min n l.length
  | [], m, n => by simp
  | _ :: xs, 0, 0 => by simp
  | x :: xs, m + 1, 0 => by simp
  | x :: xs, 0, n + 1 => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
xs : List α
n : ℕ
⊢ take 0 (x :: xs) = take (n + 1) (x :: xs) ↔ min 0 (length (x :: xs)) = min (n + 1) (length (x :: xs))

Next tactic:
simp [@eq_comm ℕ 0]