Skip to content

Commit 03e707c

Browse files
authored
69 (#275)
This PR solves problem 69.
1 parent b37f78a commit 03e707c

File tree

1 file changed

+140
-6
lines changed

1 file changed

+140
-6
lines changed

HumanEvalLean/HumanEval69.lean

Lines changed: 140 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,141 @@
11
module
22

3-
def search : Unit :=
4-
()
3+
public import Std
4+
public import Init.Data.Iterators.Lemmas.Basic
5+
open Std
6+
7+
public section
8+
9+
/-! ## Implementation -/
10+
11+
def frequencies (xs : List Nat) : TreeMap Nat Nat (fun a b => compare b a) :=
12+
xs.foldl (init := ∅) (fun freq (x : Nat) => freq.alter x (fun v? => some (v?.getD 0 + 1)))
13+
14+
def search (xs : List Nat) : Int :=
15+
let frequencies := frequencies xs
16+
let kv := frequencies.iter
17+
|>.filter (fun (k, v) => 0 < k ∧ k ≤ v)
18+
|>.map (fun (k, _) => k)
19+
|>.first?
20+
kv.getD (-1)
21+
22+
/-! ## Tests -/
23+
24+
example : search [5, 5, 5, 5, 1] = 1 := by native_decide
25+
example : search [4, 1, 4, 1, 4, 4] = 4 := by native_decide
26+
example : search [3, 3] = -1 := by native_decide
27+
example : search [8, 8, 8, 8, 8, 8, 8, 8] = 8 := by native_decide
28+
example : search [2, 3, 3, 2, 2] = 2 := by native_decide
29+
example : search [2, 7, 8, 8, 4, 8, 7, 3, 9, 6, 5, 10, 4, 3, 6, 7, 1, 7, 4, 10, 8, 1] = 1 := by native_decide
30+
example : search [3, 2, 8, 2] = 2 := by native_decide
31+
example : search [6, 7, 1, 8, 8, 10, 5, 8, 5, 3, 10] = 1 := by native_decide
32+
example : search [8, 8, 3, 6, 5, 6, 4] = -1 := by native_decide
33+
example : search [6, 9, 6, 7, 1, 4, 7, 1, 8, 8, 9, 8, 10, 10, 8, 4, 10, 4, 10, 1, 2, 9, 5, 7, 9] = 1 := by native_decide
34+
example : search [1, 9, 10, 1, 3] = 1 := by native_decide
35+
example : search [6, 9, 7, 5, 8, 7, 5, 3, 7, 5, 10, 10, 3, 6, 10, 2, 8, 6, 5, 4, 9, 5, 3, 10] = 5 := by native_decide
36+
example : search [1] = 1 := by native_decide
37+
example : search [8, 8, 10, 6, 4, 3, 5, 8, 2, 4, 2, 8, 4, 6, 10, 4, 2, 1, 10, 2, 1, 1, 5] = 4 := by native_decide
38+
example : search [2, 10, 4, 8, 2, 10, 5, 1, 2, 9, 5, 5, 6, 3, 8, 6, 4, 10] = 2 := by native_decide
39+
example : search [1, 6, 10, 1, 6, 9, 10, 8, 6, 8, 7, 3] = 1 := by native_decide
40+
example : search [9, 2, 4, 1, 5, 1, 5, 2, 5, 7, 7, 7, 3, 10, 1, 5, 4, 2, 8, 4, 1, 9, 10, 7, 10, 2, 8, 10, 9, 4] = 4 := by native_decide
41+
example : search [2, 6, 4, 2, 8, 7, 5, 6, 4, 10, 4, 6, 3, 7, 8, 8, 3, 1, 4, 2, 2, 10, 7] = 4 := by native_decide
42+
example : search [9, 8, 6, 10, 2, 6, 10, 2, 7, 8, 10, 3, 8, 2, 6, 2, 3, 1] = 2 := by native_decide
43+
example : search [5, 5, 3, 9, 5, 6, 3, 2, 8, 5, 6, 10, 10, 6, 8, 4, 10, 7, 7, 10, 8] = -1 := by native_decide
44+
example : search [10] = -1 := by native_decide
45+
example : search [9, 7, 7, 2, 4, 7, 2, 10, 9, 7, 5, 7, 2] = 2 := by native_decide
46+
example : search [5, 4, 10, 2, 1, 1, 10, 3, 6, 1, 8] = 1 := by native_decide
47+
example : search [7, 9, 9, 9, 3, 4, 1, 5, 9, 1, 2, 1, 1, 10, 7, 5, 6, 7, 6, 7, 7, 6] = 1 := by native_decide
48+
example : search [3, 10, 10, 9, 2] = -1 := by native_decide
49+
50+
/-! ## Missing API -/
51+
52+
@[simp, grind =]
53+
theorem Std.Iter.first?_toList {α β : Type w} [Iterator α Id β] [IteratorLoop α Id Id]
54+
[Iterators.Finite α Id] [LawfulIteratorLoop α Id Id] {it : Iter (α := α) β} :
55+
it.toList.head? = it.first? := by
56+
induction it using Iter.inductSteps with | step it ihy ihs
57+
rw [first?_eq_match_step, toList_eq_match_step]
58+
cases it.step using PlausibleIterStep.casesOn <;> simp [*]
59+
60+
theorem List.find?_eq_some_iff_of_pairwise_eq_lt {xs : List α} {cmp : α → α → Ordering}
61+
[OrientedCmp cmp] (h : xs.Pairwise (cmp · · = .lt)) :
62+
xs.find? P = some x ↔ x ∈ xs ∧ P x ∧ ∀ y ∈ xs, P y → (cmp x y).isLE := by
63+
rw [List.find?_eq_some_iff_append]
64+
constructor
65+
· intro h'
66+
refine ⟨by grind, by grind, ?_⟩
67+
intro y hm hy
68+
obtain ⟨as, bs, rfl, h''⟩ := h'.2
69+
have : y ∈ x :: bs := by grind
70+
simp only [pairwise_append, pairwise_cons] at h
71+
grind [Ordering.isLE_of_eq_eq, Ordering.isLE_of_eq_lt]
72+
· intro h'
73+
refine ⟨by grind, ?_⟩
74+
obtain ⟨as, bs, rfl⟩ := List.mem_iff_append.mp h'.1
75+
refine ⟨as, bs, rfl, ?_⟩
76+
intro a ha
77+
simp only [pairwise_append, pairwise_cons] at h
78+
replace h' := h'.2.2
79+
specialize h' a (by grind)
80+
have : cmp x a = .gt := by
81+
rw [OrientedCmp.eq_swap (cmp := cmp), Ordering.swap_eq_gt]
82+
grind
83+
grind [Ordering.ne_gt_iff_isLE]
84+
85+
theorem List.find?_eq_find? {xs : List α} {p q : α → Bool} (h : ∀ x ∈ xs, p x = q x) :
86+
xs.find? p = xs.find? q := by
87+
ext
88+
grind [List.find?_eq_some_iff_append]
89+
90+
theorem Option.getD_map_eq_elim {o : Option α} {f : α → β} {fallback : β} :
91+
(o.map f).getD fallback = o.elim fallback f := by
92+
cases o <;> simp
93+
94+
/-! ## Verification -/
95+
96+
theorem getElem?_frequencies {k : Nat} :
97+
(frequencies xs)[k]? = (some (xs.count k)).filter (0 < ·) := by
98+
-- We express the statement in terms of `List.foldr`, which makes the induction over `xs`
99+
-- easier because the initial tree map of the fold never changes. If the statement is expressed in
100+
-- terms of `List.foldl`, we would need to generalize the statement for general initial tree maps.
101+
rw [← List.reverse_reverse (as := xs), frequencies, List.foldl_reverse]
102+
generalize xs.reverse = xs
103+
induction xs <;> grind
104+
105+
theorem mem_frequencies :
106+
x ∈ frequencies xs ↔ x ∈ xs := by
107+
rw [← TreeMap.isSome_getElem?_iff_mem, getElem?_frequencies]
108+
simp
109+
110+
theorem search_eq_getD_find? :
111+
search xs =
112+
(frequencies xs
113+
|>.toList.find? (fun x => 0 < x.1 ∧ x.1 ≤ xs.count x.1)
114+
|>.map (↑·.fst)
115+
|>.getD (-1 : Int)) := by
116+
simp only [search, ← Iter.first?_toList, Iter.toList_map, Iter.toList_filter,
117+
TreeMap.toList_iter, List.head?_map]
118+
grind [List.find?_eq_find?, getElem?_frequencies]
119+
120+
theorem search_eq_neg_one_iff :
121+
search xs = -1 ↔ ∀ x, x = 0 ∨ xs.count x < x := by
122+
simp [search_eq_getD_find?, Option.getD_eq_iff, getElem?_frequencies]
123+
grind [List.length_filter_pos_iff]
124+
125+
theorem search_eq_iff_of_ne_neg_one (h : y ≠ -1) :
126+
search xs = y ↔ 0 < y ∧ y ≤ xs.count y.toNat ∧ ∀ z, 0 < z → z ≤ xs.count z → z ≤ y := by
127+
-- Prepare `OrientedCmp` instance to be used by `List.find?_eq_some_iff_of_pairwise_eq_lt`
128+
have : OrientedCmp (fun x y : Nat × Nat => compare y.1 x.1) := by
129+
constructor
130+
grind [Nat.compare_swap]
131+
simp only [search_eq_getD_find?, Option.getD_map_eq_elim, Option.elim]
132+
split <;> rename_i heq
133+
· simp only [List.find?_eq_some_iff_of_pairwise_eq_lt (frequencies xs).ordered_keys_toList,
134+
Prod.forall, TreeMap.mem_toList_iff_getElem?_eq_some, getElem?_frequencies] at heq
135+
grind [List.count_pos_iff, isLE_compare]
136+
· simp only [List.find?_eq_none, Prod.forall, TreeMap.mem_toList_iff_getElem?_eq_some,
137+
getElem?_frequencies, Option.filter_eq_some_iff, and_imp] at heq
138+
grind [mem_frequencies]
5139

6140
/-!
7141
## Prompt
@@ -10,8 +144,8 @@ def search : Unit :=
10144
11145
def search(lst):
12146
'''
13-
You are given a non-empty list of positive integers. Return the greatest integer that is greater than
14-
zero, and has a frequency greater than or equal to the value of the integer itself.
147+
You are given a non-empty list of positive integers. Return the greatest integer that is greater than
148+
zero, and has a frequency greater than or equal to the value of the integer itself.
15149
The frequency of an integer is the number of times it appears in the list.
16150
If no such a value exist, return -1.
17151
Examples:
@@ -32,7 +166,7 @@ def search(lst):
32166
for i in range(1, len(frq)):
33167
if frq[i] >= i:
34168
ans = i
35-
169+
36170
return ans
37171
```
38172
@@ -71,4 +205,4 @@ def check(candidate):
71205
assert candidate([3, 10, 10, 9, 2]) == -1
72206
73207
```
74-
-/
208+
-/

0 commit comments

Comments
 (0)