l3lab/ntp-mathlib huggingface dataset:
theorem of_mem_filter {a : α} : ∀ {l}, a ∈ filter p l → p a
  | b :: l, ain =>
    if pb : p b then
      have : a ∈ b :: filter p l := by simpa only [filter_cons_of_pos _ pb] using ain
      Or.elim (eq_or_mem_of_mem_cons this) (fun h : a = b => by rw [← h] at pb; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
a b : α
l : List α
ain : a ∈ filter p (b :: l)
pb : p a = true
this : a ∈ b :: filter p l
h : a = b
⊢ p a = true

Next tactic:
exact pb
theorem of_mem_filter {a : α} : ∀ {l}, a ∈ filter p l → p a
  | b :: l, ain =>
    if pb : p b then
      have : a ∈ b :: filter p l := by simpa only [filter_cons_of_pos _ pb] using ain
      Or.elim (eq_or_mem_of_mem_cons this) (fun h : a = b => by rw [← h] at pb; exact pb)
        fun h : a ∈ filter p l => of_mem_filter h
    else by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
a b : α
l : List α
ain : a ∈ filter p (b :: l)
pb : ¬p b = true
⊢ p a = true

Next tactic:
simp only [filter_cons_of_neg _ pb] at ain
theorem of_mem_filter {a : α} : ∀ {l}, a ∈ filter p l → p a
  | b :: l, ain =>
    if pb : p b then
      have : a ∈ b :: filter p l := by simpa only [filter_cons_of_pos _ pb] using ain
      Or.elim (eq_or_mem_of_mem_cons this) (fun h : a = b => by rw [← h] at pb; exact pb)
        fun h : a ∈ filter p l => of_mem_filter h
    else by simp only [filter_cons_of_neg _ pb] at ain; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
a b : α
l : List α
pb : ¬p b = true
ain : a ∈ filter p l
⊢ p a = true

Next tactic:
exact of_mem_filter ain
theorem mem_filter_of_mem {a : α} : ∀ {l}, a ∈ l → p a → a ∈ filter p l
  | x :: l, h, h1 => by
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
a x : α
l : List α
h : a ∈ x :: l
h1 : p a = true
⊢ a ∈ filter p (x :: l)

Next tactic:
rcases mem_cons.1 h with rfl | h
theorem mem_filter_of_mem {a : α} : ∀ {l}, a ∈ l → p a → a ∈ filter p l
  | x :: l, h, h1 => by
    rcases mem_cons.1 h with rfl | h
    · 

Proof state:
case inl
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
a : α
l : List α
h1 : p a = true
h : a ∈ a :: l
⊢ a ∈ filter p (a :: l)

Next tactic:
simp [filter, h1]
theorem mem_filter_of_mem {a : α} : ∀ {l}, a ∈ l → p a → a ∈ filter p l
  | x :: l, h, h1 => by
    rcases mem_cons.1 h with rfl | h
    · simp [filter, h1]
    · 

Proof state:
case inr
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
a x : α
l : List α
h✝ : a ∈ x :: l
h1 : p a = true
h : a ∈ l
⊢ a ∈ filter p (x :: l)

Next tactic:
rw [filter]
theorem mem_filter_of_mem {a : α} : ∀ {l}, a ∈ l → p a → a ∈ filter p l
  | x :: l, h, h1 => by
    rcases mem_cons.1 h with rfl | h
    · simp [filter, h1]
    · rw [filter]
      

Proof state:
case inr
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
a x : α
l : List α
h✝ : a ∈ x :: l
h1 : p a = true
h : a ∈ l
⊢ a ∈
    match p x with
    | true => x :: filter p l
    | false => filter p l

Next tactic:
cases p x
theorem mem_filter_of_mem {a : α} : ∀ {l}, a ∈ l → p a → a ∈ filter p l
  | x :: l, h, h1 => by
    rcases mem_cons.1 h with rfl | h
    · simp [filter, h1]
    · rw [filter]
      cases p x <;> 

Proof state:
case inr.false
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
a x : α
l : List α
h✝ : a ∈ x :: l
h1 : p a = true
h : a ∈ l
⊢ a ∈
    match false with
    | true => x :: filter p l
    | false => filter p l

Next tactic:
simp [mem_filter_of_mem h h1]
theorem mem_filter_of_mem {a : α} : ∀ {l}, a ∈ l → p a → a ∈ filter p l
  | x :: l, h, h1 => by
    rcases mem_cons.1 h with rfl | h
    · simp [filter, h1]
    · rw [filter]
      cases p x <;> 

Proof state:
case inr.true
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
a x : α
l : List α
h✝ : a ∈ x :: l
h1 : p a = true
h : a ∈ l
⊢ a ∈
    match true with
    | true => x :: filter p l
    | false => filter p l

Next tactic:
simp [mem_filter_of_mem h h1]
theorem monotone_filter_left (p : α → Bool) ⦃l l' : List α⦄ (h : l ⊆ l') :
    filter p l ⊆ filter p l' := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p : α → Bool
l l' : List α
h : l ⊆ l'
⊢ filter p l ⊆ filter p l'

Next tactic:
intro x hx
theorem monotone_filter_left (p : α → Bool) ⦃l l' : List α⦄ (h : l ⊆ l') :
    filter p l ⊆ filter p l' := by
  intro x hx
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p : α → Bool
l l' : List α
h : l ⊆ l'
x : α
hx : x ∈ filter p l
⊢ x ∈ filter p l'

Next tactic:
rw [mem_filter] at hx ⊢
theorem monotone_filter_left (p : α → Bool) ⦃l l' : List α⦄ (h : l ⊆ l') :
    filter p l ⊆ filter p l' := by
  intro x hx
  rw [mem_filter] at hx ⊢
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p : α → Bool
l l' : List α
h : l ⊆ l'
x : α
hx : x ∈ l ∧ p x = true
⊢ x ∈ l' ∧ p x = true

Next tactic:
exact ⟨h hx.left, hx.right⟩
theorem monotone_filter_right (l : List α) ⦃p q : α → Bool⦄
    (h : ∀ a, p a → q a) : l.filter p <+ l.filter q := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ : α → Bool
l : List α
p q : α → Bool
h : ∀ (a : α), p a = true → q a = true
⊢ filter p l <+ filter q l

Next tactic:
induction' l with hd tl IH
theorem monotone_filter_right (l : List α) ⦃p q : α → Bool⦄
    (h : ∀ a, p a → q a) : l.filter p <+ l.filter q := by
  induction' l with hd tl IH
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p q : α → Bool
h : ∀ (a : α), p a = true → q a = true
⊢ filter p [] <+ filter q []

Next tactic:
rfl
theorem monotone_filter_right (l : List α) ⦃p q : α → Bool⦄
    (h : ∀ a, p a → q a) : l.filter p <+ l.filter q := by
  induction' l with hd tl IH
  · rfl
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p q : α → Bool
h : ∀ (a : α), p a = true → q a = true
hd : α
tl : List α
IH : filter p tl <+ filter q tl
⊢ filter p (hd :: tl) <+ filter q (hd :: tl)

Next tactic:
by_cases hp : p hd
theorem monotone_filter_right (l : List α) ⦃p q : α → Bool⦄
    (h : ∀ a, p a → q a) : l.filter p <+ l.filter q := by
  induction' l with hd tl IH
  · rfl
  · by_cases hp : p hd
    · 

Proof state:
case pos
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p q : α → Bool
h : ∀ (a : α), p a = true → q a = true
hd : α
tl : List α
IH : filter p tl <+ filter q tl
hp : p hd = true
⊢ filter p (hd :: tl) <+ filter q (hd :: tl)

Next tactic:
rw [filter_cons_of_pos _ hp, filter_cons_of_pos _ (h _ hp)]
theorem monotone_filter_right (l : List α) ⦃p q : α → Bool⦄
    (h : ∀ a, p a → q a) : l.filter p <+ l.filter q := by
  induction' l with hd tl IH
  · rfl
  · by_cases hp : p hd
    · rw [filter_cons_of_pos _ hp, filter_cons_of_pos _ (h _ hp)]
      

Proof state:
case pos
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p q : α → Bool
h : ∀ (a : α), p a = true → q a = true
hd : α
tl : List α
IH : filter p tl <+ filter q tl
hp : p hd = true
⊢ hd :: filter p tl <+ hd :: filter q tl

Next tactic:
exact IH.cons_cons hd
theorem monotone_filter_right (l : List α) ⦃p q : α → Bool⦄
    (h : ∀ a, p a → q a) : l.filter p <+ l.filter q := by
  induction' l with hd tl IH
  · rfl
  · by_cases hp : p hd
    · rw [filter_cons_of_pos _ hp, filter_cons_of_pos _ (h _ hp)]
      exact IH.cons_cons hd
    · 

Proof state:
case neg
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p q : α → Bool
h : ∀ (a : α), p a = true → q a = true
hd : α
tl : List α
IH : filter p tl <+ filter q tl
hp : ¬p hd = true
⊢ filter p (hd :: tl) <+ filter q (hd :: tl)

Next tactic:
rw [filter_cons_of_neg _ hp]
theorem monotone_filter_right (l : List α) ⦃p q : α → Bool⦄
    (h : ∀ a, p a → q a) : l.filter p <+ l.filter q := by
  induction' l with hd tl IH
  · rfl
  · by_cases hp : p hd
    · rw [filter_cons_of_pos _ hp, filter_cons_of_pos _ (h _ hp)]
      exact IH.cons_cons hd
    · rw [filter_cons_of_neg _ hp]
      

Proof state:
case neg
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p q : α → Bool
h : ∀ (a : α), p a = true → q a = true
hd : α
tl : List α
IH : filter p tl <+ filter q tl
hp : ¬p hd = true
⊢ filter p tl <+ filter q (hd :: tl)

Next tactic:
by_cases hq : q hd
theorem monotone_filter_right (l : List α) ⦃p q : α → Bool⦄
    (h : ∀ a, p a → q a) : l.filter p <+ l.filter q := by
  induction' l with hd tl IH
  · rfl
  · by_cases hp : p hd
    · rw [filter_cons_of_pos _ hp, filter_cons_of_pos _ (h _ hp)]
      exact IH.cons_cons hd
    · rw [filter_cons_of_neg _ hp]
      by_cases hq : q hd
      · 

Proof state:
case pos
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p q : α → Bool
h : ∀ (a : α), p a = true → q a = true
hd : α
tl : List α
IH : filter p tl <+ filter q tl
hp : ¬p hd = true
hq : q hd = true
⊢ filter p tl <+ filter q (hd :: tl)

Next tactic:
rw [filter_cons_of_pos _ hq]
theorem monotone_filter_right (l : List α) ⦃p q : α → Bool⦄
    (h : ∀ a, p a → q a) : l.filter p <+ l.filter q := by
  induction' l with hd tl IH
  · rfl
  · by_cases hp : p hd
    · rw [filter_cons_of_pos _ hp, filter_cons_of_pos _ (h _ hp)]
      exact IH.cons_cons hd
    · rw [filter_cons_of_neg _ hp]
      by_cases hq : q hd
      · rw [filter_cons_of_pos _ hq]
        

Proof state:
case pos
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p q : α → Bool
h : ∀ (a : α), p a = true → q a = true
hd : α
tl : List α
IH : filter p tl <+ filter q tl
hp : ¬p hd = true
hq : q hd = true
⊢ filter p tl <+ hd :: filter q tl

Next tactic:
exact sublist_cons_of_sublist hd IH
theorem monotone_filter_right (l : List α) ⦃p q : α → Bool⦄
    (h : ∀ a, p a → q a) : l.filter p <+ l.filter q := by
  induction' l with hd tl IH
  · rfl
  · by_cases hp : p hd
    · rw [filter_cons_of_pos _ hp, filter_cons_of_pos _ (h _ hp)]
      exact IH.cons_cons hd
    · rw [filter_cons_of_neg _ hp]
      by_cases hq : q hd
      · rw [filter_cons_of_pos _ hq]
        exact sublist_cons_of_sublist hd IH
      · 

Proof state:
case neg
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p q : α → Bool
h : ∀ (a : α), p a = true → q a = true
hd : α
tl : List α
IH : filter p tl <+ filter q tl
hp : ¬p hd = true
hq : ¬q hd = true
⊢ filter p tl <+ filter q (hd :: tl)

Next tactic:
rw [filter_cons_of_neg _ hq]
theorem monotone_filter_right (l : List α) ⦃p q : α → Bool⦄
    (h : ∀ a, p a → q a) : l.filter p <+ l.filter q := by
  induction' l with hd tl IH
  · rfl
  · by_cases hp : p hd
    · rw [filter_cons_of_pos _ hp, filter_cons_of_pos _ (h _ hp)]
      exact IH.cons_cons hd
    · rw [filter_cons_of_neg _ hp]
      by_cases hq : q hd
      · rw [filter_cons_of_pos _ hq]
        exact sublist_cons_of_sublist hd IH
      · rw [filter_cons_of_neg _ hq]
        

Proof state:
case neg
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p q : α → Bool
h : ∀ (a : α), p a = true → q a = true
hd : α
tl : List α
IH : filter p tl <+ filter q tl
hp : ¬p hd = true
hq : ¬q hd = true
⊢ filter p tl <+ filter q tl

Next tactic:
exact IH
lemma map_filter' {f : α → β} (hf : Injective f) (l : List α)
    [DecidablePred fun b => ∃ a, p a ∧ f a = b] :
    (l.filter p).map f = (l.map f).filter fun b => ∃ a, p a ∧ f a = b := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
f : α → β
hf : Injective f
l : List α
inst✝ : DecidablePred fun b => ∃ a, p a = true ∧ f a = b
⊢ map f (filter p l) = filter (fun b => decide (∃ a, p a = true ∧ f a = b)) (map f l)

Next tactic:
simp [(· ∘ ·), map_filter, hf.eq_iff]
lemma filter_attach' (l : List α) (p : {a // a ∈ l} → Bool) [DecidableEq α] :
    l.attach.filter p =
      (l.filter fun x => ∃ h, p ⟨x, h⟩).attach.map (Subtype.map id fun x => mem_of_mem_filter) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ : α → Bool
l : List α
p : { a // a ∈ l } → Bool
inst✝ : DecidableEq α
⊢ filter p (attach l) =
    map
      (Subtype.map id
        (_ : ∀ (x : α), x ∈ filter (fun x => decide (∃ h, p { val := x, property := h } = true)) l → x ∈ l))
      (attach (filter (fun x => decide (∃ h, p { val := x, property := h } = true)) l))

Next tactic:
classical
  refine' map_injective_iff.2 Subtype.coe_injective _
  simp [(· ∘ ·), map_filter' _ Subtype.coe_injective]
lemma filter_attach' (l : List α) (p : {a // a ∈ l} → Bool) [DecidableEq α] :
    l.attach.filter p =
      (l.filter fun x => ∃ h, p ⟨x, h⟩).attach.map (Subtype.map id fun x => mem_of_mem_filter) := by
  classical
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ : α → Bool
l : List α
p : { a // a ∈ l } → Bool
inst✝ : DecidableEq α
⊢ filter p (attach l) =
    map
      (Subtype.map id
        (_ : ∀ (x : α), x ∈ filter (fun x => decide (∃ h, p { val := x, property := h } = true)) l → x ∈ l))
      (attach (filter (fun x => decide (∃ h, p { val := x, property := h } = true)) l))

Next tactic:
refine' map_injective_iff.2 Subtype.coe_injective _
lemma filter_attach' (l : List α) (p : {a // a ∈ l} → Bool) [DecidableEq α] :
    l.attach.filter p =
      (l.filter fun x => ∃ h, p ⟨x, h⟩).attach.map (Subtype.map id fun x => mem_of_mem_filter) := by
  classical
  refine' map_injective_iff.2 Subtype.coe_injective _
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ : α → Bool
l : List α
p : { a // a ∈ l } → Bool
inst✝ : DecidableEq α
⊢ map (fun a => ↑a) (filter p (attach l)) =
    map (fun a => ↑a)
      (map
        (Subtype.map id
          (_ : ∀ (x : α), x ∈ filter (fun x => decide (∃ h, p { val := x, property := h } = true)) l → x ∈ l))
        (attach (filter (fun x => decide (∃ h, p { val := x, property := h } = true)) l)))

Next tactic:
simp [(· ∘ ·), map_filter' _ Subtype.coe_injective]
lemma filter_attach (l : List α) (p : α → Bool) :
    (l.attach.filter fun x => p x : List {x // x ∈ l}) =
      (l.filter p).attach.map (Subtype.map id fun x => mem_of_mem_filter) :=
  map_injective_iff.2 Subtype.coe_injective <| by
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ : α → Bool
l : List α
p : α → Bool
⊢ map (fun a => ↑a) (filter (fun x => p ↑x) (attach l)) =
    map (fun a => ↑a) (map (Subtype.map id (_ : ∀ (x : α), x ∈ filter p l → x ∈ l)) (attach (filter p l)))

Next tactic:
simp_rw [map_map, (· ∘ ·), Subtype.map, id.def, ← Function.comp_apply (g := Subtype.val),
      ← map_filter, attach_map_val]
lemma filter_comm (q) (l : List α) : filter p (filter q l) = filter q (filter p l) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p q : α → Bool
l : List α
⊢ filter p (filter q l) = filter q (filter p l)

Next tactic:
simp [and_comm]
@[simp]
theorem filter_true (l : List α) :
    filter (fun _ => true) l = l := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
l : List α
⊢ filter (fun x => true) l = l

Next tactic:
induction l
@[simp]
theorem filter_true (l : List α) :
    filter (fun _ => true) l = l := by induction l <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
⊢ filter (fun x => true) [] = []

Next tactic:
simp [*, filter]
@[simp]
theorem filter_true (l : List α) :
    filter (fun _ => true) l = l := by induction l <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
head✝ : α
tail✝ : List α
tail_ih✝ : filter (fun x => true) tail✝ = tail✝
⊢ filter (fun x => true) (head✝ :: tail✝) = head✝ :: tail✝

Next tactic:
simp [*, filter]
@[simp]
theorem filter_false (l : List α) :
    filter (fun _ => false) l = [] := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
l : List α
⊢ filter (fun x => false) l = []

Next tactic:
induction l
@[simp]
theorem filter_false (l : List α) :
    filter (fun _ => false) l = [] := by induction l <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
⊢ filter (fun x => false) [] = []

Next tactic:
simp [*, filter]
@[simp]
theorem filter_false (l : List α) :
    filter (fun _ => false) l = [] := by induction l <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
head✝ : α
tail✝ : List α
tail_ih✝ : filter (fun x => false) tail✝ = []
⊢ filter (fun x => false) (head✝ :: tail✝) = []

Next tactic:
simp [*, filter]
theorem span.loop_eq_take_drop :
    ∀ l₁ l₂ : List α, span.loop p l₁ l₂ = (l₂.reverse ++ takeWhile p l₁, dropWhile p l₁)
  | [], l₂ => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂✝ : List α
p : α → Bool
l₂ : List α
⊢ loop p [] l₂ = (reverse l₂ ++ takeWhile p [], dropWhile p [])

Next tactic:
simp [span.loop, takeWhile, dropWhile]
theorem span.loop_eq_take_drop :
    ∀ l₁ l₂ : List α, span.loop p l₁ l₂ = (l₂.reverse ++ takeWhile p l₁, dropWhile p l₁)
  | [], l₂ => by simp [span.loop, takeWhile, dropWhile]
  | (a :: l), l₂ => by
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂✝ : List α
p : α → Bool
a : α
l l₂ : List α
⊢ loop p (a :: l) l₂ = (reverse l₂ ++ takeWhile p (a :: l), dropWhile p (a :: l))

Next tactic:
cases hp : p a
theorem span.loop_eq_take_drop :
    ∀ l₁ l₂ : List α, span.loop p l₁ l₂ = (l₂.reverse ++ takeWhile p l₁, dropWhile p l₁)
  | [], l₂ => by simp [span.loop, takeWhile, dropWhile]
  | (a :: l), l₂ => by
    cases hp : p a <;> 

Proof state:
case false
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂✝ : List α
p : α → Bool
a : α
l l₂ : List α
hp : p a = false
⊢ loop p (a :: l) l₂ = (reverse l₂ ++ takeWhile p (a :: l), dropWhile p (a :: l))

Next tactic:
simp [hp, span.loop, span.loop_eq_take_drop, takeWhile, dropWhile]
theorem span.loop_eq_take_drop :
    ∀ l₁ l₂ : List α, span.loop p l₁ l₂ = (l₂.reverse ++ takeWhile p l₁, dropWhile p l₁)
  | [], l₂ => by simp [span.loop, takeWhile, dropWhile]
  | (a :: l), l₂ => by
    cases hp : p a <;> 

Proof state:
case true
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂✝ : List α
p : α → Bool
a : α
l l₂ : List α
hp : p a = true
⊢ loop p (a :: l) l₂ = (reverse l₂ ++ takeWhile p (a :: l), dropWhile p (a :: l))

Next tactic:
simp [hp, span.loop, span.loop_eq_take_drop, takeWhile, dropWhile]
@[simp]
theorem span_eq_take_drop (l : List α) : span p l = (takeWhile p l, dropWhile p l) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
l : List α
⊢ span p l = (takeWhile p l, dropWhile p l)

Next tactic:
simpa using span.loop_eq_take_drop p l []
theorem dropWhile_nthLe_zero_not (l : List α) (hl : 0 < (l.dropWhile p).length) :
    ¬p ((l.dropWhile p).nthLe 0 hl) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
l : List α
hl : 0 < length (dropWhile p l)
⊢ ¬p (nthLe (dropWhile p l) 0 hl) = true

Next tactic:
induction' l with hd tl IH
theorem dropWhile_nthLe_zero_not (l : List α) (hl : 0 < (l.dropWhile p).length) :
    ¬p ((l.dropWhile p).nthLe 0 hl) := by
  induction' l with hd tl IH
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
hl : 0 < length (dropWhile p [])
⊢ ¬p (nthLe (dropWhile p []) 0 hl) = true

Next tactic:
cases hl
theorem dropWhile_nthLe_zero_not (l : List α) (hl : 0 < (l.dropWhile p).length) :
    ¬p ((l.dropWhile p).nthLe 0 hl) := by
  induction' l with hd tl IH
  · cases hl
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
hd : α
tl : List α
IH : ∀ (hl : 0 < length (dropWhile p tl)), ¬p (nthLe (dropWhile p tl) 0 hl) = true
hl : 0 < length (dropWhile p (hd :: tl))
⊢ ¬p (nthLe (dropWhile p (hd :: tl)) 0 hl) = true

Next tactic:
simp only [dropWhile]
theorem dropWhile_nthLe_zero_not (l : List α) (hl : 0 < (l.dropWhile p).length) :
    ¬p ((l.dropWhile p).nthLe 0 hl) := by
  induction' l with hd tl IH
  · cases hl
  · simp only [dropWhile]
    

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
hd : α
tl : List α
IH : ∀ (hl : 0 < length (dropWhile p tl)), ¬p (nthLe (dropWhile p tl) 0 hl) = true
hl : 0 < length (dropWhile p (hd :: tl))
⊢ ¬p
        (nthLe
          (match p hd with
          | true => dropWhile p tl
          | false => hd :: tl)
          0
          (_ :
            0 <
              length
                (match p hd with
                | true => dropWhile p tl
                | false => hd :: tl))) =
      true

Next tactic:
by_cases hp : p hd
theorem dropWhile_nthLe_zero_not (l : List α) (hl : 0 < (l.dropWhile p).length) :
    ¬p ((l.dropWhile p).nthLe 0 hl) := by
  induction' l with hd tl IH
  · cases hl
  · simp only [dropWhile]
    by_cases hp : p hd
    · 

Proof state:
case pos
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
hd : α
tl : List α
IH : ∀ (hl : 0 < length (dropWhile p tl)), ¬p (nthLe (dropWhile p tl) 0 hl) = true
hl : 0 < length (dropWhile p (hd :: tl))
hp : p hd = true
⊢ ¬p
        (nthLe
          (match p hd with
          | true => dropWhile p tl
          | false => hd :: tl)
          0
          (_ :
            0 <
              length
                (match p hd with
                | true => dropWhile p tl
                | false => hd :: tl))) =
      true

Next tactic:
simp [hp, IH]
theorem dropWhile_nthLe_zero_not (l : List α) (hl : 0 < (l.dropWhile p).length) :
    ¬p ((l.dropWhile p).nthLe 0 hl) := by
  induction' l with hd tl IH
  · cases hl
  · simp only [dropWhile]
    by_cases hp : p hd
    · simp [hp, IH]
    · 

Proof state:
case neg
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
hd : α
tl : List α
IH : ∀ (hl : 0 < length (dropWhile p tl)), ¬p (nthLe (dropWhile p tl) 0 hl) = true
hl : 0 < length (dropWhile p (hd :: tl))
hp : ¬p hd = true
⊢ ¬p
        (nthLe
          (match p hd with
          | true => dropWhile p tl
          | false => hd :: tl)
          0
          (_ :
            0 <
              length
                (match p hd with
                | true => dropWhile p tl
                | false => hd :: tl))) =
      true

Next tactic:
simp [hp, nthLe_cons]
@[simp]
theorem dropWhile_eq_nil_iff : dropWhile p l = [] ↔ ∀ x ∈ l, p x := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
l : List α
⊢ dropWhile p l = [] ↔ ∀ (x : α), x ∈ l → p x = true

Next tactic:
induction' l with x xs IH
@[simp]
theorem dropWhile_eq_nil_iff : dropWhile p l = [] ↔ ∀ x ∈ l, p x := by
  induction' l with x xs IH
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
l : List α
⊢ dropWhile p [] = [] ↔ ∀ (x : α), x ∈ [] → p x = true

Next tactic:
simp [dropWhile]
@[simp]
theorem dropWhile_eq_nil_iff : dropWhile p l = [] ↔ ∀ x ∈ l, p x := by
  induction' l with x xs IH
  · simp [dropWhile]
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
l : List α
x : α
xs : List α
IH : dropWhile p xs = [] ↔ ∀ (x : α), x ∈ xs → p x = true
⊢ dropWhile p (x :: xs) = [] ↔ ∀ (x_1 : α), x_1 ∈ x :: xs → p x_1 = true

Next tactic:
by_cases hp : p x
@[simp]
theorem dropWhile_eq_nil_iff : dropWhile p l = [] ↔ ∀ x ∈ l, p x := by
  induction' l with x xs IH
  · simp [dropWhile]
  · by_cases hp : p x <;> 

Proof state:
case pos
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
l : List α
x : α
xs : List α
IH : dropWhile p xs = [] ↔ ∀ (x : α), x ∈ xs → p x = true
hp : p x = true
⊢ dropWhile p (x :: xs) = [] ↔ ∀ (x_1 : α), x_1 ∈ x :: xs → p x_1 = true

Next tactic:
simp [hp, dropWhile, IH]
@[simp]
theorem dropWhile_eq_nil_iff : dropWhile p l = [] ↔ ∀ x ∈ l, p x := by
  induction' l with x xs IH
  · simp [dropWhile]
  · by_cases hp : p x <;> 

Proof state:
case neg
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
l : List α
x : α
xs : List α
IH : dropWhile p xs = [] ↔ ∀ (x : α), x ∈ xs → p x = true
hp : ¬p x = true
⊢ dropWhile p (x :: xs) = [] ↔ ∀ (x_1 : α), x_1 ∈ x :: xs → p x_1 = true

Next tactic:
simp [hp, dropWhile, IH]