l3lab/ntp-mathlib huggingface dataset:
/-- If `find p = some i`, then `p i` holds -/
theorem find_spec :
    ∀ {n : ℕ} (p : Fin n → Prop) [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p), p i
  | 0, p, I, i, hi => Option.noConfusion hi
  | n + 1, p, I, i, hi => by
    rw [find] at hi
    cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
    · 

Proof state:
case none
m n✝ n : ℕ
p : Fin (n + 1) → Prop
I : DecidablePred p
i : Fin (n + 1)
hi :
  i ∈
    Option.casesOn (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) (if x : p (last n) then some (last n) else none)
      fun i => some (castLT i (_ : ↑i < Nat.succ n))
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
⊢ p i

Next tactic:
rw [h] at hi
/-- If `find p = some i`, then `p i` holds -/
theorem find_spec :
    ∀ {n : ℕ} (p : Fin n → Prop) [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p), p i
  | 0, p, I, i, hi => Option.noConfusion hi
  | n + 1, p, I, i, hi => by
    rw [find] at hi
    cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
    · rw [h] at hi
      

Proof state:
case none
m n✝ n : ℕ
p : Fin (n + 1) → Prop
I : DecidablePred p
i : Fin (n + 1)
hi :
  i ∈
    Option.casesOn none (if x : p (last n) then some (last n) else none) fun i => some (castLT i (_ : ↑i < Nat.succ n))
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
⊢ p i

Next tactic:
dsimp at hi
/-- If `find p = some i`, then `p i` holds -/
theorem find_spec :
    ∀ {n : ℕ} (p : Fin n → Prop) [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p), p i
  | 0, p, I, i, hi => Option.noConfusion hi
  | n + 1, p, I, i, hi => by
    rw [find] at hi
    cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
    · rw [h] at hi
      dsimp at hi
      

Proof state:
case none
m n✝ n : ℕ
p : Fin (n + 1) → Prop
I : DecidablePred p
i : Fin (n + 1)
hi : i ∈ if p (last n) then some (last n) else none
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
⊢ p i

Next tactic:
split_ifs at hi with hl
/-- If `find p = some i`, then `p i` holds -/
theorem find_spec :
    ∀ {n : ℕ} (p : Fin n → Prop) [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p), p i
  | 0, p, I, i, hi => Option.noConfusion hi
  | n + 1, p, I, i, hi => by
    rw [find] at hi
    cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
    · rw [h] at hi
      dsimp at hi
      split_ifs at hi with hl
      · 

Proof state:
case pos
m n✝ n : ℕ
p : Fin (n + 1) → Prop
I : DecidablePred p
i : Fin (n + 1)
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
hl : p (last n)
hi : i ∈ some (last n)
⊢ p i

Next tactic:
simp only [Option.mem_def, Option.some.injEq] at hi
/-- If `find p = some i`, then `p i` holds -/
theorem find_spec :
    ∀ {n : ℕ} (p : Fin n → Prop) [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p), p i
  | 0, p, I, i, hi => Option.noConfusion hi
  | n + 1, p, I, i, hi => by
    rw [find] at hi
    cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
    · rw [h] at hi
      dsimp at hi
      split_ifs at hi with hl
      · simp only [Option.mem_def, Option.some.injEq] at hi
        

Proof state:
case pos
m n✝ n : ℕ
p : Fin (n + 1) → Prop
I : DecidablePred p
i : Fin (n + 1)
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
hl : p (last n)
hi : last n = i
⊢ p i

Next tactic:
exact hi ▸ hl
/-- If `find p = some i`, then `p i` holds -/
theorem find_spec :
    ∀ {n : ℕ} (p : Fin n → Prop) [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p), p i
  | 0, p, I, i, hi => Option.noConfusion hi
  | n + 1, p, I, i, hi => by
    rw [find] at hi
    cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
    · rw [h] at hi
      dsimp at hi
      split_ifs at hi with hl
      · simp only [Option.mem_def, Option.some.injEq] at hi
        exact hi ▸ hl
      · 

Proof state:
case neg
m n✝ n : ℕ
p : Fin (n + 1) → Prop
I : DecidablePred p
i : Fin (n + 1)
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
hl : ¬p (last n)
hi : i ∈ none
⊢ p i

Next tactic:
exact (Option.not_mem_none _ hi).elim
/-- If `find p = some i`, then `p i` holds -/
theorem find_spec :
    ∀ {n : ℕ} (p : Fin n → Prop) [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p), p i
  | 0, p, I, i, hi => Option.noConfusion hi
  | n + 1, p, I, i, hi => by
    rw [find] at hi
    cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
    · rw [h] at hi
      dsimp at hi
      split_ifs at hi with hl
      · simp only [Option.mem_def, Option.some.injEq] at hi
        exact hi ▸ hl
      · exact (Option.not_mem_none _ hi).elim
    · 

Proof state:
case some
m n✝ n : ℕ
p : Fin (n + 1) → Prop
I : DecidablePred p
i : Fin (n + 1)
hi :
  i ∈
    Option.casesOn (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) (if x : p (last n) then some (last n) else none)
      fun i => some (castLT i (_ : ↑i < Nat.succ n))
j : Fin n
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = some j
⊢ p i

Next tactic:
rw [h] at hi
/-- If `find p = some i`, then `p i` holds -/
theorem find_spec :
    ∀ {n : ℕ} (p : Fin n → Prop) [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p), p i
  | 0, p, I, i, hi => Option.noConfusion hi
  | n + 1, p, I, i, hi => by
    rw [find] at hi
    cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
    · rw [h] at hi
      dsimp at hi
      split_ifs at hi with hl
      · simp only [Option.mem_def, Option.some.injEq] at hi
        exact hi ▸ hl
      · exact (Option.not_mem_none _ hi).elim
    · rw [h] at hi
      

Proof state:
case some
m n✝ n : ℕ
p : Fin (n + 1) → Prop
I : DecidablePred p
i : Fin (n + 1)
j : Fin n
hi :
  i ∈
    Option.casesOn (some j) (if x : p (last n) then some (last n) else none) fun i =>
      some (castLT i (_ : ↑i < Nat.succ n))
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = some j
⊢ p i

Next tactic:
dsimp at hi
/-- If `find p = some i`, then `p i` holds -/
theorem find_spec :
    ∀ {n : ℕ} (p : Fin n → Prop) [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p), p i
  | 0, p, I, i, hi => Option.noConfusion hi
  | n + 1, p, I, i, hi => by
    rw [find] at hi
    cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
    · rw [h] at hi
      dsimp at hi
      split_ifs at hi with hl
      · simp only [Option.mem_def, Option.some.injEq] at hi
        exact hi ▸ hl
      · exact (Option.not_mem_none _ hi).elim
    · rw [h] at hi
      dsimp at hi
      

Proof state:
case some
m n✝ n : ℕ
p : Fin (n + 1) → Prop
I : DecidablePred p
i : Fin (n + 1)
j : Fin n
hi : i ∈ some (castLT j (_ : ↑j < Nat.succ n))
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = some j
⊢ p i

Next tactic:
rw [← Option.some_inj.1 hi]
/-- If `find p = some i`, then `p i` holds -/
theorem find_spec :
    ∀ {n : ℕ} (p : Fin n → Prop) [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p), p i
  | 0, p, I, i, hi => Option.noConfusion hi
  | n + 1, p, I, i, hi => by
    rw [find] at hi
    cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
    · rw [h] at hi
      dsimp at hi
      split_ifs at hi with hl
      · simp only [Option.mem_def, Option.some.injEq] at hi
        exact hi ▸ hl
      · exact (Option.not_mem_none _ hi).elim
    · rw [h] at hi
      dsimp at hi
      rw [← Option.some_inj.1 hi]
      

Proof state:
case some
m n✝ n : ℕ
p : Fin (n + 1) → Prop
I : DecidablePred p
i : Fin (n + 1)
j : Fin n
hi : i ∈ some (castLT j (_ : ↑j < Nat.succ n))
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = some j
⊢ p (castLT j (_ : ↑j < Nat.succ n))

Next tactic:
refine @find_spec n (fun i ↦ p (i.castLT (Nat.lt_succ_of_lt i.2))) _ _ h
/-- `find p` does not return `none` if and only if `p i` holds at some index `i`. -/
theorem isSome_find_iff :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p], (find p).isSome ↔ ∃ i, p i
  | 0, p, _ => iff_of_false (fun h ↦ Bool.noConfusion h) fun ⟨i, _⟩ ↦ Fin.elim0' i
  | n + 1, p, _ =>
    ⟨fun h ↦ by
      

Proof state:
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝ : DecidablePred p
h : Option.isSome (find p) = true
⊢ ∃ i, p i

Next tactic:
rw [Option.isSome_iff_exists] at h
/-- `find p` does not return `none` if and only if `p i` holds at some index `i`. -/
theorem isSome_find_iff :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p], (find p).isSome ↔ ∃ i, p i
  | 0, p, _ => iff_of_false (fun h ↦ Bool.noConfusion h) fun ⟨i, _⟩ ↦ Fin.elim0' i
  | n + 1, p, _ =>
    ⟨fun h ↦ by
      rw [Option.isSome_iff_exists] at h
      

Proof state:
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝ : DecidablePred p
h : ∃ a, find p = some a
⊢ ∃ i, p i

Next tactic:
cases' h with i hi
/-- `find p` does not return `none` if and only if `p i` holds at some index `i`. -/
theorem isSome_find_iff :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p], (find p).isSome ↔ ∃ i, p i
  | 0, p, _ => iff_of_false (fun h ↦ Bool.noConfusion h) fun ⟨i, _⟩ ↦ Fin.elim0' i
  | n + 1, p, _ =>
    ⟨fun h ↦ by
      rw [Option.isSome_iff_exists] at h
      cases' h with i hi
      

Proof state:
case intro
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝ : DecidablePred p
i : Fin (n + 1)
hi : find p = some i
⊢ ∃ i, p i

Next tactic:
exact ⟨i, find_spec _ hi⟩
/-- `find p` does not return `none` if and only if `p i` holds at some index `i`. -/
theorem isSome_find_iff :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p], (find p).isSome ↔ ∃ i, p i
  | 0, p, _ => iff_of_false (fun h ↦ Bool.noConfusion h) fun ⟨i, _⟩ ↦ Fin.elim0' i
  | n + 1, p, _ =>
    ⟨fun h ↦ by
      rw [Option.isSome_iff_exists] at h
      cases' h with i hi
      exact ⟨i, find_spec _ hi⟩, fun ⟨⟨i, hin⟩, hi⟩ ↦ by
      

Proof state:
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝¹ : DecidablePred p
x✝ : ∃ i, p i
i : ℕ
hin : i < n + 1
hi : p { val := i, isLt := hin }
⊢ Option.isSome (find p) = true

Next tactic:
dsimp [find]
/-- `find p` does not return `none` if and only if `p i` holds at some index `i`. -/
theorem isSome_find_iff :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p], (find p).isSome ↔ ∃ i, p i
  | 0, p, _ => iff_of_false (fun h ↦ Bool.noConfusion h) fun ⟨i, _⟩ ↦ Fin.elim0' i
  | n + 1, p, _ =>
    ⟨fun h ↦ by
      rw [Option.isSome_iff_exists] at h
      cases' h with i hi
      exact ⟨i, find_spec _ hi⟩, fun ⟨⟨i, hin⟩, hi⟩ ↦ by
      dsimp [find]
      

Proof state:
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝¹ : DecidablePred p
x✝ : ∃ i, p i
i : ℕ
hin : i < n + 1
hi : p { val := i, isLt := hin }
⊢ Option.isSome
      (Option.rec (if p (last n) then some (last n) else none) (fun val => some (castLT val (_ : ↑val < Nat.succ n)))
        (find fun i => p (castLT i (_ : ↑i < Nat.succ n)))) =
    true

Next tactic:
cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
/-- `find p` does not return `none` if and only if `p i` holds at some index `i`. -/
theorem isSome_find_iff :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p], (find p).isSome ↔ ∃ i, p i
  | 0, p, _ => iff_of_false (fun h ↦ Bool.noConfusion h) fun ⟨i, _⟩ ↦ Fin.elim0' i
  | n + 1, p, _ =>
    ⟨fun h ↦ by
      rw [Option.isSome_iff_exists] at h
      cases' h with i hi
      exact ⟨i, find_spec _ hi⟩, fun ⟨⟨i, hin⟩, hi⟩ ↦ by
      dsimp [find]
      cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
      · 

Proof state:
case none
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝¹ : DecidablePred p
x✝ : ∃ i, p i
i : ℕ
hin : i < n + 1
hi : p { val := i, isLt := hin }
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
⊢ Option.isSome
      (Option.rec (if p (last n) then some (last n) else none) (fun val => some (castLT val (_ : ↑val < Nat.succ n)))
        none) =
    true

Next tactic:
split_ifs with hl
/-- `find p` does not return `none` if and only if `p i` holds at some index `i`. -/
theorem isSome_find_iff :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p], (find p).isSome ↔ ∃ i, p i
  | 0, p, _ => iff_of_false (fun h ↦ Bool.noConfusion h) fun ⟨i, _⟩ ↦ Fin.elim0' i
  | n + 1, p, _ =>
    ⟨fun h ↦ by
      rw [Option.isSome_iff_exists] at h
      cases' h with i hi
      exact ⟨i, find_spec _ hi⟩, fun ⟨⟨i, hin⟩, hi⟩ ↦ by
      dsimp [find]
      cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
      · split_ifs with hl
        · 

Proof state:
case pos
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝¹ : DecidablePred p
x✝ : ∃ i, p i
i : ℕ
hin : i < n + 1
hi : p { val := i, isLt := hin }
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
hl : p (last n)
⊢ Option.isSome (Option.rec (some (last n)) (fun val => some (castLT val (_ : ↑val < Nat.succ n))) none) = true

Next tactic:
exact Option.isSome_some
/-- `find p` does not return `none` if and only if `p i` holds at some index `i`. -/
theorem isSome_find_iff :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p], (find p).isSome ↔ ∃ i, p i
  | 0, p, _ => iff_of_false (fun h ↦ Bool.noConfusion h) fun ⟨i, _⟩ ↦ Fin.elim0' i
  | n + 1, p, _ =>
    ⟨fun h ↦ by
      rw [Option.isSome_iff_exists] at h
      cases' h with i hi
      exact ⟨i, find_spec _ hi⟩, fun ⟨⟨i, hin⟩, hi⟩ ↦ by
      dsimp [find]
      cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
      · split_ifs with hl
        · exact Option.isSome_some
        · 

Proof state:
case neg
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝¹ : DecidablePred p
x✝ : ∃ i, p i
i : ℕ
hin : i < n + 1
hi : p { val := i, isLt := hin }
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
hl : ¬p (last n)
⊢ Option.isSome (Option.rec none (fun val => some (castLT val (_ : ↑val < Nat.succ n))) none) = true

Next tactic:
have := (@isSome_find_iff n (fun x ↦ p (x.castLT (Nat.lt_succ_of_lt x.2))) _).2
              ⟨⟨i, lt_of_le_of_ne (Nat.le_of_lt_succ hin) fun h ↦ by cases h; exact hl hi⟩, hi⟩
/-- `find p` does not return `none` if and only if `p i` holds at some index `i`. -/
theorem isSome_find_iff :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p], (find p).isSome ↔ ∃ i, p i
  | 0, p, _ => iff_of_false (fun h ↦ Bool.noConfusion h) fun ⟨i, _⟩ ↦ Fin.elim0' i
  | n + 1, p, _ =>
    ⟨fun h ↦ by
      rw [Option.isSome_iff_exists] at h
      cases' h with i hi
      exact ⟨i, find_spec _ hi⟩, fun ⟨⟨i, hin⟩, hi⟩ ↦ by
      dsimp [find]
      cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
      · split_ifs with hl
        · exact Option.isSome_some
        · have := (@isSome_find_iff n (fun x ↦ p (x.castLT (Nat.lt_succ_of_lt x.2))) _).2
              ⟨⟨i, lt_of_le_of_ne (Nat.le_of_lt_succ hin) fun h ↦ by 

Proof state:
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝¹ : DecidablePred p
x✝ : ∃ i, p i
i : ℕ
hin : i < n + 1
hi : p { val := i, isLt := hin }
h✝ : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
hl : ¬p (last n)
h : i = n
⊢ False

Next tactic:
cases h
/-- `find p` does not return `none` if and only if `p i` holds at some index `i`. -/
theorem isSome_find_iff :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p], (find p).isSome ↔ ∃ i, p i
  | 0, p, _ => iff_of_false (fun h ↦ Bool.noConfusion h) fun ⟨i, _⟩ ↦ Fin.elim0' i
  | n + 1, p, _ =>
    ⟨fun h ↦ by
      rw [Option.isSome_iff_exists] at h
      cases' h with i hi
      exact ⟨i, find_spec _ hi⟩, fun ⟨⟨i, hin⟩, hi⟩ ↦ by
      dsimp [find]
      cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
      · split_ifs with hl
        · exact Option.isSome_some
        · have := (@isSome_find_iff n (fun x ↦ p (x.castLT (Nat.lt_succ_of_lt x.2))) _).2
              ⟨⟨i, lt_of_le_of_ne (Nat.le_of_lt_succ hin) fun h ↦ by cases h; 

Proof state:
case refl
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝¹ : DecidablePred p
x✝ : ∃ i, p i
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
hl : ¬p (last n)
hin : n < n + 1
hi : p { val := n, isLt := hin }
⊢ False

Next tactic:
exact hl hi
/-- `find p` does not return `none` if and only if `p i` holds at some index `i`. -/
theorem isSome_find_iff :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p], (find p).isSome ↔ ∃ i, p i
  | 0, p, _ => iff_of_false (fun h ↦ Bool.noConfusion h) fun ⟨i, _⟩ ↦ Fin.elim0' i
  | n + 1, p, _ =>
    ⟨fun h ↦ by
      rw [Option.isSome_iff_exists] at h
      cases' h with i hi
      exact ⟨i, find_spec _ hi⟩, fun ⟨⟨i, hin⟩, hi⟩ ↦ by
      dsimp [find]
      cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
      · split_ifs with hl
        · exact Option.isSome_some
        · have := (@isSome_find_iff n (fun x ↦ p (x.castLT (Nat.lt_succ_of_lt x.2))) _).2
              ⟨⟨i, lt_of_le_of_ne (Nat.le_of_lt_succ hin) fun h ↦ by cases h; exact hl hi⟩, hi⟩
          

Proof state:
case neg
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝¹ : DecidablePred p
x✝ : ∃ i, p i
i : ℕ
hin : i < n + 1
hi : p { val := i, isLt := hin }
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
hl : ¬p (last n)
this : Option.isSome (find fun x => p (castLT x (_ : ↑x < Nat.succ n))) = true
⊢ Option.isSome (Option.rec none (fun val => some (castLT val (_ : ↑val < Nat.succ n))) none) = true

Next tactic:
rw [h] at this
/-- `find p` does not return `none` if and only if `p i` holds at some index `i`. -/
theorem isSome_find_iff :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p], (find p).isSome ↔ ∃ i, p i
  | 0, p, _ => iff_of_false (fun h ↦ Bool.noConfusion h) fun ⟨i, _⟩ ↦ Fin.elim0' i
  | n + 1, p, _ =>
    ⟨fun h ↦ by
      rw [Option.isSome_iff_exists] at h
      cases' h with i hi
      exact ⟨i, find_spec _ hi⟩, fun ⟨⟨i, hin⟩, hi⟩ ↦ by
      dsimp [find]
      cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
      · split_ifs with hl
        · exact Option.isSome_some
        · have := (@isSome_find_iff n (fun x ↦ p (x.castLT (Nat.lt_succ_of_lt x.2))) _).2
              ⟨⟨i, lt_of_le_of_ne (Nat.le_of_lt_succ hin) fun h ↦ by cases h; exact hl hi⟩, hi⟩
          rw [h] at this
          

Proof state:
case neg
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝¹ : DecidablePred p
x✝ : ∃ i, p i
i : ℕ
hin : i < n + 1
hi : p { val := i, isLt := hin }
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
hl : ¬p (last n)
this : Option.isSome none = true
⊢ Option.isSome (Option.rec none (fun val => some (castLT val (_ : ↑val < Nat.succ n))) none) = true

Next tactic:
exact this
/-- `find p` does not return `none` if and only if `p i` holds at some index `i`. -/
theorem isSome_find_iff :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p], (find p).isSome ↔ ∃ i, p i
  | 0, p, _ => iff_of_false (fun h ↦ Bool.noConfusion h) fun ⟨i, _⟩ ↦ Fin.elim0' i
  | n + 1, p, _ =>
    ⟨fun h ↦ by
      rw [Option.isSome_iff_exists] at h
      cases' h with i hi
      exact ⟨i, find_spec _ hi⟩, fun ⟨⟨i, hin⟩, hi⟩ ↦ by
      dsimp [find]
      cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with j
      · split_ifs with hl
        · exact Option.isSome_some
        · have := (@isSome_find_iff n (fun x ↦ p (x.castLT (Nat.lt_succ_of_lt x.2))) _).2
              ⟨⟨i, lt_of_le_of_ne (Nat.le_of_lt_succ hin) fun h ↦ by cases h; exact hl hi⟩, hi⟩
          rw [h] at this
          exact this
      · 

Proof state:
case some
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝¹ : DecidablePred p
x✝ : ∃ i, p i
i : ℕ
hin : i < n + 1
hi : p { val := i, isLt := hin }
j : Fin n
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = some j
⊢ Option.isSome
      (Option.rec (if p (last n) then some (last n) else none) (fun val => some (castLT val (_ : ↑val < Nat.succ n)))
        (some j)) =
    true

Next tactic:
simp
/-- `find p` returns `none` if and only if `p i` never holds. -/
theorem find_eq_none_iff {n : ℕ} {p : Fin n → Prop} [DecidablePred p] :
    find p = none ↔ ∀ i, ¬p i := by 

Proof state:
m n✝ n : ℕ
p : Fin n → Prop
inst✝ : DecidablePred p
⊢ find p = none ↔ ∀ (i : Fin n), ¬p i

Next tactic:
rw [← not_exists, ← isSome_find_iff]
/-- `find p` returns `none` if and only if `p i` never holds. -/
theorem find_eq_none_iff {n : ℕ} {p : Fin n → Prop} [DecidablePred p] :
    find p = none ↔ ∀ i, ¬p i := by rw [← not_exists, ← isSome_find_iff]; 

Proof state:
m n✝ n : ℕ
p : Fin n → Prop
inst✝ : DecidablePred p
⊢ find p = none ↔ ¬Option.isSome (find fun x => p x) = true

Next tactic:
cases find p
/-- `find p` returns `none` if and only if `p i` never holds. -/
theorem find_eq_none_iff {n : ℕ} {p : Fin n → Prop} [DecidablePred p] :
    find p = none ↔ ∀ i, ¬p i := by rw [← not_exists, ← isSome_find_iff]; cases find p <;> 

Proof state:
case none
m n✝ n : ℕ
p : Fin n → Prop
inst✝ : DecidablePred p
⊢ none = none ↔ ¬Option.isSome none = true

Next tactic:
simp
/-- `find p` returns `none` if and only if `p i` never holds. -/
theorem find_eq_none_iff {n : ℕ} {p : Fin n → Prop} [DecidablePred p] :
    find p = none ↔ ∀ i, ¬p i := by rw [← not_exists, ← isSome_find_iff]; cases find p <;> 

Proof state:
case some
m n✝ n : ℕ
p : Fin n → Prop
inst✝ : DecidablePred p
val✝ : Fin n
⊢ some val✝ = none ↔ ¬Option.isSome (some val✝) = true

Next tactic:
simp
/-- If `find p` returns `some i`, then `p j` does not hold for `j < i`, i.e., `i` is minimal among
the indices where `p` holds. -/
theorem find_min :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p) {j : Fin n}
      (_ : j < i), ¬p j
  | 0, p, _, i, hi, _, _, _ => Option.noConfusion hi
  | n + 1, p, _, i, hi, ⟨j, hjn⟩, hj, hpj => by
    

Proof state:
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝ : DecidablePred p
i : Fin (n + 1)
hi : i ∈ find p
j : ℕ
hjn : j < n + 1
hj : { val := j, isLt := hjn } < i
hpj : p { val := j, isLt := hjn }
⊢ False

Next tactic:
rw [find] at hi
/-- If `find p` returns `some i`, then `p j` does not hold for `j < i`, i.e., `i` is minimal among
the indices where `p` holds. -/
theorem find_min :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p) {j : Fin n}
      (_ : j < i), ¬p j
  | 0, p, _, i, hi, _, _, _ => Option.noConfusion hi
  | n + 1, p, _, i, hi, ⟨j, hjn⟩, hj, hpj => by
    rw [find] at hi
    

Proof state:
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝ : DecidablePred p
i : Fin (n + 1)
hi :
  i ∈
    Option.casesOn (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) (if x : p (last n) then some (last n) else none)
      fun i => some (castLT i (_ : ↑i < Nat.succ n))
j : ℕ
hjn : j < n + 1
hj : { val := j, isLt := hjn } < i
hpj : p { val := j, isLt := hjn }
⊢ False

Next tactic:
cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with k
/-- If `find p` returns `some i`, then `p j` does not hold for `j < i`, i.e., `i` is minimal among
the indices where `p` holds. -/
theorem find_min :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p) {j : Fin n}
      (_ : j < i), ¬p j
  | 0, p, _, i, hi, _, _, _ => Option.noConfusion hi
  | n + 1, p, _, i, hi, ⟨j, hjn⟩, hj, hpj => by
    rw [find] at hi
    cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with k
    · 

Proof state:
case none
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝ : DecidablePred p
i : Fin (n + 1)
hi :
  i ∈
    Option.casesOn (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) (if x : p (last n) then some (last n) else none)
      fun i => some (castLT i (_ : ↑i < Nat.succ n))
j : ℕ
hjn : j < n + 1
hj : { val := j, isLt := hjn } < i
hpj : p { val := j, isLt := hjn }
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
⊢ False

Next tactic:
simp only [h] at hi
/-- If `find p` returns `some i`, then `p j` does not hold for `j < i`, i.e., `i` is minimal among
the indices where `p` holds. -/
theorem find_min :
    ∀ {n : ℕ} {p : Fin n → Prop} [DecidablePred p] {i : Fin n} (_ : i ∈ Fin.find p) {j : Fin n}
      (_ : j < i), ¬p j
  | 0, p, _, i, hi, _, _, _ => Option.noConfusion hi
  | n + 1, p, _, i, hi, ⟨j, hjn⟩, hj, hpj => by
    rw [find] at hi
    cases' h : find fun i : Fin n ↦ p (i.castLT (Nat.lt_succ_of_lt i.2)) with k
    · simp only [h] at hi
      

Proof state:
case none
m n✝ n : ℕ
p : Fin (n + 1) → Prop
x✝ : DecidablePred p
i : Fin (n + 1)
j : ℕ
hjn : j < n + 1
hj : { val := j, isLt := hjn } < i
hpj : p { val := j, isLt := hjn }
h : (find fun i => p (castLT i (_ : ↑i < Nat.succ n))) = none
hi : i ∈ if x : p (last n) then some (last n) else none
⊢ False

Next tactic:
split_ifs at hi with hl