Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 4cca114

Browse files
ChrisHughes24mergify[bot]
authored andcommitted
feat(data/fin): fin.find (#1167)
* feat(data/fin): fin.find * add nat_find_mem_find
1 parent 3ee1f85 commit 4cca114

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

src/data/fin.lean

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,98 @@ by cases i; refl
208208

209209
end rec
210210

211+
section find
212+
213+
def find : Π {n : ℕ} (p : fin n → Prop) [decidable_pred p], option (fin n)
214+
| 0 p _ := none
215+
| (n+1) p _ := by resetI; exact option.cases_on
216+
(@find n (λ i, p (i.cast_lt (nat.lt_succ_of_lt i.2))) _)
217+
(if h : p (fin.last n) then some (fin.last n) else none)
218+
(λ i, some (i.cast_lt (nat.lt_succ_of_lt i.2)))
219+
220+
lemma find_spec : Π {n : ℕ} (p : fin n → Prop) [decidable_pred p] {i : fin n}
221+
(hi : i ∈ by exactI fin.find p), p i
222+
| 0 p I i hi := option.no_confusion hi
223+
| (n+1) p I i hi := begin
224+
dsimp [find] at hi,
225+
resetI,
226+
cases h : find (λ i : fin n, (p (i.cast_lt (nat.lt_succ_of_lt i.2)))) with j,
227+
{ rw h at hi,
228+
dsimp at hi,
229+
split_ifs at hi with hl hl,
230+
{ exact option.some_inj.1 hi ▸ hl },
231+
{ exact option.no_confusion hi } },
232+
{ rw h at hi,
233+
rw [← option.some_inj.1 hi],
234+
exact find_spec _ h }
235+
end
236+
237+
lemma is_some_find_iff : Π {n : ℕ} {p : fin n → Prop} [decidable_pred p],
238+
by exactI (find p).is_some ↔ ∃ i, p i
239+
| 0 p _ := iff_of_false (λ h, bool.no_confusion h) (λ ⟨i, _⟩, fin.elim0 i)
240+
| (n+1) p _ := ⟨λ h, begin
241+
resetI,
242+
rw [option.is_some_iff_exists] at h,
243+
cases h with i hi,
244+
exact ⟨i, find_spec _ hi⟩
245+
end, λ ⟨⟨i, hin⟩, hi⟩,
246+
begin
247+
resetI,
248+
dsimp [find],
249+
cases h : find (λ i : fin n, (p (i.cast_lt (nat.lt_succ_of_lt i.2)))) with j,
250+
{ split_ifs with hl hl,
251+
{ exact option.is_some_some },
252+
{ have := (@is_some_find_iff n (λ x, p (x.cast_lt (nat.lt_succ_of_lt x.2))) _).2
253+
⟨⟨i, lt_of_le_of_ne (nat.le_of_lt_succ hin)
254+
(λ h, by clear_aux_decl; subst h; exact hl hi)⟩, hi⟩,
255+
rw h at this,
256+
exact this } },
257+
{ simp }
258+
end
259+
260+
lemma find_eq_none_iff {n : ℕ} {p : fin n → Prop} [decidable_pred p] :
261+
find p = none ↔ ∀ i, ¬ p i :=
262+
by rw [← not_exists, ← is_some_find_iff]; cases (find p); simp
263+
264+
lemma find_min : Π {n : ℕ} {p : fin n → Prop} [decidable_pred p] {i : fin n}
265+
(hi : i ∈ by exactI fin.find p) {j : fin n} (hj : j < i), ¬ p j
266+
| 0 p _ i hi j hj hpj := option.no_confusion hi
267+
| (n+1) p _ i hi ⟨j, hjn⟩ hj hpj := begin
268+
resetI,
269+
dsimp [find] at hi,
270+
cases h : find (λ i : fin n, (p (i.cast_lt (nat.lt_succ_of_lt i.2)))) with k,
271+
{ rw [h] at hi,
272+
split_ifs at hi with hl hl,
273+
{ have := option.some_inj.1 hi,
274+
subst this,
275+
rw [find_eq_none_iff] at h,
276+
exact h ⟨j, hj⟩ hpj },
277+
{ exact option.no_confusion hi } },
278+
{ rw h at hi,
279+
dsimp at hi,
280+
have := option.some_inj.1 hi,
281+
subst this,
282+
exact find_min h (show (⟨j, lt_trans hj k.2⟩ : fin n) < k, from hj) hpj }
283+
end
284+
285+
lemma find_min' {p : fin n → Prop} [decidable_pred p] {i : fin n}
286+
(h : i ∈ fin.find p) {j : fin n} (hj : p j) : i ≤ j :=
287+
le_of_not_gt (λ hij, find_min h hij hj)
288+
289+
lemma nat_find_mem_find {p : fin n → Prop} [decidable_pred p]
290+
(h : ∃ i, ∃ hin : i < n, p ⟨i, hin⟩) :
291+
(⟨nat.find h, (nat.find_spec h).fst⟩ : fin n) ∈ find p :=
292+
let ⟨i, hin, hi⟩ := h in
293+
begin
294+
cases hf : find p with f,
295+
{ rw [find_eq_none_iff] at hf,
296+
exact (hf ⟨i, hin⟩ hi).elim },
297+
{ refine option.some_inj.2 (le_antisymm _ _),
298+
{ exact find_min' hf (nat.find_spec h).snd },
299+
{ exact nat.find_min' _ ⟨f.2, by convert find_spec p hf;
300+
exact fin.eta _ _⟩ } }
301+
end
302+
303+
end find
304+
211305
end fin

0 commit comments

Comments
 (0)