Skip to content

Commit 58cd912

Browse files
authored
70 (#276)
This PR solves problem 70.
1 parent 202175c commit 58cd912

File tree

1 file changed

+316
-3
lines changed

1 file changed

+316
-3
lines changed

HumanEvalLean/HumanEval70.lean

Lines changed: 316 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,320 @@
11
module
22

3-
def strange_sort_list : Unit :=
4-
()
3+
/-! ## Implementation -/
4+
5+
def strangeSortArray (xs : Array Int) : Array Int :=
6+
let sorted := xs.mergeSort
7+
Array.ofFn (n := sorted.size)
8+
(fun i => if i.val % 2 = 0 then sorted[i.val / 2] else sorted[sorted.size - 1 - i.val / 2])
9+
10+
/-! ## Tests -/
11+
12+
example : strangeSortArray #[1, 2, 3, 4] = #[1, 4, 2, 3] := by native_decide
13+
example : strangeSortArray #[5, 6, 7, 8, 9] = #[5, 9, 6, 8, 7] := by native_decide
14+
example : strangeSortArray #[1, 2, 3, 4, 5] = #[1, 5, 2, 4, 3] := by native_decide
15+
example : strangeSortArray #[5, 6, 7, 8, 9, 1] = #[1, 9, 5, 8, 6, 7] := by native_decide
16+
example : strangeSortArray #[5, 5, 5, 5] = #[5, 5, 5, 5] := by native_decide
17+
example : strangeSortArray #[] = #[] := by native_decide
18+
example : strangeSortArray #[1, 2, 3, 4, 5, 6, 7, 8] = #[1, 8, 2, 7, 3, 6, 4, 5] := by native_decide
19+
example : strangeSortArray #[0, 2, 2, 2, 5, 5, -5, -5] = #[-5, 5, -5, 5, 0, 2, 2, 2] := by native_decide
20+
example : strangeSortArray #[111111] = #[111111] := by native_decide
21+
22+
/-! ## Missing API -/
23+
24+
theorem List.all_min?_mem {xs : List Int} :
25+
xs.min?.all (· ∈ xs) := by
26+
simp only [Option.all_eq_true_iff_get]
27+
grind
28+
29+
-- Helps grind to derive `b ∈ xs` from `xs.min? = some b`
30+
grind_pattern List.all_min?_mem => xs.min?
31+
32+
theorem List.Perm.min_eq [LE α] [Min α] [Std.LawfulOrderMin α] [Std.IsLinearOrder α]
33+
{xs ys : List α} (h_perm : xs.Perm ys) (h : xs ≠ []) :
34+
xs.min h = ys.min (by grind [Perm.eq_nil]) := by
35+
simp only [List.min_eq_iff]
36+
grind
37+
38+
theorem List.Perm.min?_eq [LE α] [Min α] [Std.LawfulOrderMin α] [Std.IsLinearOrder α]
39+
{xs ys : List α} (h_perm : xs.Perm ys) :
40+
xs.min? = ys.min? := by
41+
match xs, ys with
42+
| [], [] => rfl
43+
| x :: xs, y :: ys =>
44+
rw [min?_eq_some_min, min?_eq_some_min, h_perm.min_eq]
45+
simp
46+
| x :: xs, [] | [], y :: ys => grind [Perm.nil_eq, Perm.eq_nil]
47+
48+
theorem List.Perm.max_eq [LE α] [Max α] [Std.LawfulOrderMax α] [Std.IsLinearOrder α]
49+
{xs ys : List α} (h_perm : xs.Perm ys) (h : xs ≠ []) :
50+
xs.max h = ys.max (by grind [Perm.eq_nil]) := by
51+
simp only [List.max_eq_iff]
52+
grind
53+
54+
theorem List.Perm.max?_eq [LE α] [Max α] [Std.LawfulOrderMax α] [Std.IsLinearOrder α]
55+
{xs ys : List α} (h_perm : xs.Perm ys) :
56+
xs.max? = ys.max? := by
57+
match xs, ys with
58+
| [], [] => rfl
59+
| x :: xs, y :: ys =>
60+
rw [max?_eq_some_max, max?_eq_some_max, h_perm.max_eq]
61+
simp
62+
| x :: xs, [] | [], y :: ys => grind [Perm.nil_eq, Perm.eq_nil]
63+
64+
theorem Array.Perm.max?_eq [LE α] [Max α] [Std.LawfulOrderMax α] [Std.IsLinearOrder α]
65+
{xs ys : Array α} (h_perm : xs.Perm ys) :
66+
xs.max? = ys.max? := by
67+
simp [← max?_toList, h_perm.toList.max?_eq]
68+
69+
theorem Array.Perm.min?_eq [LE α] [Min α] [Std.LawfulOrderMin α] [Std.IsLinearOrder α]
70+
{xs ys : Array α} (h_perm : xs.Perm ys) :
71+
xs.min? = ys.min? := by
72+
simp [← min?_toList, h_perm.toList.min?_eq]
73+
74+
theorem List.max_eq_getLast [Max α] {xs : List α} (h) (hp : xs.Pairwise (fun a b => max a b = b)) :
75+
xs.max h = xs.getLast h := by
76+
rw [List.max.eq_def]
77+
split
78+
rename_i x xs _
79+
suffices ∀ xs : List α, (x :: xs.reverse).Pairwise (fun a b => max a b = b) → foldl max x xs.reverse = (x :: xs.reverse).getLast (by grind) by
80+
simp +singlePass only [← List.reverse_reverse (as := xs)]
81+
grind
82+
simp [- pairwise_cons]
83+
intro xs hp
84+
induction xs
85+
· simp
86+
· simp
87+
rename_i ih
88+
rw [ih]
89+
· rw [List.reverse_cons, ← List.cons_append, pairwise_append] at hp <;> grind
90+
· grind
91+
92+
theorem List.max?_eq_getLast? [Max α] {xs : List α} (hp : xs.Pairwise (fun a b => max a b = b)) :
93+
xs.max? = xs.getLast? := by
94+
cases xs
95+
· simp
96+
· rw [max?_eq_some_max, max_eq_getLast, getLast?_eq_some_getLast]
97+
· simp
98+
· exact hp
99+
100+
theorem Array.max_eq_back [Max α] {xs : Array α} (h) (hp : xs.toList.Pairwise (fun a b => max a b = b)) :
101+
xs.max h = xs.back (by grind) := by
102+
rw [← max_toList, List.max_eq_getLast, getLast_toList]
103+
· exact hp
104+
· simp [h]
105+
106+
theorem Array.max?_eq_back? [Max α] {xs : Array α} (hp : xs.toList.Pairwise (fun a b => max a b = b)) :
107+
xs.max? = xs.back? := by
108+
simp [← max?_toList, List.max?_eq_getLast? hp]
109+
110+
theorem Std.min_eq_left_iff [LE α] [Min α] [Std.Refl (α := α) (· ≤ ·)]
111+
[Std.LawfulOrderLeftLeaningMin α] {a b : α} :
112+
min a b = a ↔ a ≤ b := by
113+
by_cases a ≤ b
114+
· grind [Std.LawfulOrderLeftLeaningMin.min_eq_left]
115+
· rename_i h
116+
simp only [Std.LawfulOrderLeftLeaningMin.min_eq_right _ _ h, iff_false, h]
117+
rintro rfl
118+
exact h.elim (Std.Refl.refl _)
119+
120+
theorem Std.max_eq_right_iff [LE α] [Max α] [Std.IsLinearOrder α] [Std.LawfulOrderMax α]
121+
{a b : α} :
122+
max a b = b ↔ a ≤ b := by
123+
open scoped Classical in grind [max_eq_if]
124+
125+
theorem List.getElem_zero_mergeSort {xs : List Int} (h) :
126+
xs.mergeSort[0]'h = xs.min (by grind [length_mergeSort]) := by
127+
rw [(xs.mergeSort_perm (· ≤ ·)).symm.min_eq, List.min_eq_head, List.head_eq_getElem]
128+
simp only [Std.min_eq_left_iff]
129+
simpa using xs.pairwise_mergeSort (by grind) (by grind) (le := (· ≤ ·))
130+
131+
theorem Array.getElem_zero_mergeSort {xs : Array Int} (h) :
132+
xs.mergeSort[0]'h = xs.min (by grind [size_mergeSort]) := by
133+
simp only [mergeSort_eq_toArray_mergeSort_toList, List.getElem_toArray,
134+
List.getElem_zero_mergeSort, min_toList]
135+
136+
theorem List.getElem_length_sub_one_mergeSort {xs : List Int} (h) :
137+
xs.mergeSort[xs.length - 1]'h = xs.max (by grind [length_mergeSort]) := by
138+
rw [(xs.mergeSort_perm (· ≤ ·)).symm.max_eq, List.max_eq_getLast, List.getLast_eq_getElem]
139+
· simp [List.length_mergeSort]
140+
· simp only [Std.max_eq_right_iff]
141+
simpa using xs.pairwise_mergeSort (by grind) (by grind) (le := (· ≤ ·))
142+
143+
theorem Array.getElem_size_sub_one_mergeSort {xs : Array Int} (h) :
144+
xs.mergeSort[xs.size - 1]'h = xs.max (by grind [size_mergeSort]) := by
145+
simp only [mergeSort_eq_toArray_mergeSort_toList]
146+
simp only [← length_toList, List.getElem_toArray]
147+
rw [List.getElem_length_sub_one_mergeSort, max_toList]
148+
149+
theorem List.max_erase_le_max {xs : List Int} (h) :
150+
(xs.erase x).max h ≤ xs.max (by grind) := by
151+
simp only [List.max_le_iff]
152+
intro b hb
153+
apply List.le_max_of_mem
154+
exact List.mem_of_mem_erase hb
155+
156+
theorem Array.max_erase_le_max {xs : Array Int} {h} :
157+
(xs.erase x).max h ≤ xs.max (by grind) := by
158+
simp only [Array.max_le_iff]
159+
intro b hb
160+
apply Array.le_max_of_mem
161+
exact Array.mem_of_mem_erase hb
162+
163+
theorem List.count_dropLast [BEq α] {xs : List α} {a : α} :
164+
xs.dropLast.count a = xs.count a - if xs.getLast? == some a then 1 else 0 := by
165+
rw [← List.reverse_reverse (as := xs)]
166+
generalize xs.reverse = xs
167+
rw [dropLast_reverse, count_reverse, count_tail, getLast?_reverse, count_reverse]
168+
169+
theorem Array.count_pop [BEq α] {xs : Array α} {a : α} :
170+
xs.pop.count a = xs.count a - if xs.back? == some a then 1 else 0 := by
171+
rw [← count_toList, toList_pop, List.count_dropLast, getLast?_toList, count_toList]
172+
173+
/--
174+
If two lists are sorted by an antisymmetric relation, and permutations of each other,
175+
they must be equal.
176+
-/
177+
theorem Array.Perm.eq_of_pairwise {xs ys : Array α}
178+
(h : ∀ a b, a ∈ xs → b ∈ ys → le a b → le b a → a = b)
179+
(hpx : xs.toList.Pairwise le) (hpy : ys.toList.Pairwise le) (hp : xs.Perm ys) :
180+
xs = ys := by
181+
rw [← toList_inj]
182+
apply List.Perm.eq_of_pairwise (by simpa) hpx hpy (by simpa [perm_iff_toList_perm] using hp)
183+
184+
theorem Array.pop_eq_take {xs : Array α} :
185+
xs.pop = xs.take (xs.size - 1) := by
186+
rw [take_eq_extract, extract_eq_pop rfl]
187+
188+
theorem List.Pairwise.toList_arrayTake {xs : Array α} (h : xs.toList.Pairwise R) :
189+
(xs.take i).toList.Pairwise R := by
190+
simp only [Array.take_eq_extract, Array.toList_extract, extract_eq_take_drop, Nat.sub_zero,
191+
drop_zero]
192+
apply List.Pairwise.take
193+
exact h
194+
195+
theorem List.Pairwise.toList_arrayDrop {xs : Array α} (h : xs.toList.Pairwise R) :
196+
(xs.drop i).toList.Pairwise R := by
197+
simp only [Array.drop_eq_extract, Array.toList_extract, extract_eq_drop_take']
198+
apply List.Pairwise.drop
199+
apply List.Pairwise.take
200+
exact h
201+
202+
theorem Array.Perm.countP_eq [BEq α] {xs ys : Array α} (hp : xs.Perm ys) :
203+
xs.countP P = ys.countP P := by
204+
simp [← countP_toList, hp.toList.countP_eq]
205+
206+
theorem Array.Perm.count_eq [BEq α] {xs ys : Array α} (hp : xs.Perm ys) :
207+
xs.count a = ys.count a :=
208+
hp.countP_eq
209+
210+
theorem Array.head?_toList {xs : Array α} :
211+
xs.toList.head? = xs[0]? := by
212+
simp [List.head?_eq_getElem?]
213+
214+
@[grind =]
215+
theorem Array.count_drop_one [BEq α] {xs : Array α} {a : α} :
216+
(xs.drop 1).count a = xs.count a - if xs[0]? == some a then 1 else 0 := by
217+
have := List.count_tail (l := xs.toList) (a := a)
218+
simp [← count_toList, List.take_of_length_le, this, head?_toList]
219+
220+
theorem Array.min?_eq_getElem?_zero {α : Type u} [Min α] {xs : Array α}
221+
(h : xs.toList.Pairwise (fun a b => min a b = a)) : xs.min? = xs[0]? := by
222+
simp [← min?_toList, List.min?_eq_head? h, List.head?_eq_getElem?]
223+
224+
/-! ## Verification -/
225+
226+
theorem strangeSortArray_empty :
227+
strangeSortArray #[] = #[] := by
228+
grind [strangeSortArray, Array.mergeSort_empty]
229+
230+
theorem strangeSortArray_singleton :
231+
strangeSortArray #[x] = #[x] := by
232+
ext <;> grind [strangeSortArray, Array.mergeSort_singleton, Array.size_ofFn, Array.getElem_ofFn]
233+
234+
theorem mergeSort_erase_max {xs : Array Int} {h} :
235+
(xs.erase (xs.max h)).mergeSort = xs.mergeSort.pop := by
236+
apply Array.Perm.eq_of_pairwise (le := (· ≤ ·))
237+
· grind
238+
· simpa using Array.pairwise_mergeSort (α := Int) (le := (· ≤ ·)) (by grind) (by grind)
239+
· simp only [Array.pop_eq_take]
240+
apply List.Pairwise.toList_arrayTake
241+
simpa using Array.pairwise_mergeSort (α := Int) (le := (· ≤ ·)) (by grind) (by grind)
242+
· refine Array.Perm.trans Array.mergeSort_perm ?_
243+
simp only [Array.perm_iff_toList_perm, List.perm_iff_count, Array.count_toList]
244+
intro a
245+
rw [Array.count_erase]
246+
have h_mem : xs.max h ∈ xs := by grind
247+
rw [Array.count_pop, Array.mergeSort_perm.count_eq,
248+
← Array.max?_eq_back?, Array.mergeSort_perm.max?_eq,
249+
Array.max?_eq_some_max]
250+
· simp
251+
· grind
252+
· simp only [Std.max_eq_right_iff]
253+
simpa using Array.pairwise_mergeSort (α := Int) (le := (· ≤ ·)) (by grind) (by grind)
254+
255+
theorem mergeSort_erase_min {xs : Array Int} {h} :
256+
(xs.erase (xs.min h)).mergeSort = xs.mergeSort.drop 1 := by
257+
apply Array.Perm.eq_of_pairwise (le := (· ≤ ·))
258+
· grind
259+
· simpa using Array.pairwise_mergeSort (α := Int) (le := (· ≤ ·)) (by grind) (by grind)
260+
· apply List.Pairwise.toList_arrayDrop
261+
simpa using Array.pairwise_mergeSort (α := Int) (le := (· ≤ ·)) (by grind) (by grind)
262+
· refine Array.Perm.trans Array.mergeSort_perm ?_
263+
simp only [Array.perm_iff_toList_perm, List.perm_iff_count, Array.count_toList]
264+
intro a
265+
rw [Array.count_erase]
266+
have h_mem : xs.max h ∈ xs := by grind
267+
rw [Array.count_drop_one, Array.mergeSort_perm.count_eq,
268+
← Array.min?_eq_getElem?_zero, Array.mergeSort_perm.min?_eq,
269+
Array.min?_eq_some_min]
270+
· simp
271+
· grind
272+
· simp only [Std.min_eq_left_iff]
273+
simpa using Array.pairwise_mergeSort (α := Int) (le := (· ≤ ·)) (by grind) (by grind)
274+
275+
theorem size_strangeSortArray {xs : Array Int} :
276+
(strangeSortArray xs).size = xs.size := by
277+
simp [strangeSortArray]
278+
279+
theorem strangeSortArray_of_two_le_size (h : 2 ≤ xs.size) :
280+
let minimum := xs.min (by grind)
281+
let withoutMin := xs.erase minimum
282+
let maximum := withoutMin.max (by grind)
283+
let withoutMinMax := withoutMin.erase maximum
284+
strangeSortArray xs = #[minimum, maximum] ++ strangeSortArray withoutMinMax := by
285+
intro minimum withoutMin maximum withoutMinMax
286+
ext
287+
· simp [strangeSortArray]
288+
grind
289+
· rename_i i h₁ h₂
290+
simp [strangeSortArray]
291+
match i with
292+
| 0 => grind [Array.getElem_zero_mergeSort]
293+
| 1 =>
294+
simp [Array.getElem_size_sub_one_mergeSort, maximum, withoutMin]
295+
rw [Array.max_eq_iff]
296+
constructor
297+
· grind [Array.mem_of_mem_erase]
298+
· intro b hb
299+
by_cases hb' : b = minimum
300+
· cases hb'
301+
simp only [minimum]
302+
apply Array.min_le_of_mem
303+
exact Array.mem_of_mem_erase (Array.max_mem _)
304+
· apply Array.le_max_of_mem
305+
rwa [Array.mem_erase_of_ne]
306+
assumption
307+
| j + 2 =>
308+
have : withoutMinMax.mergeSort = xs.mergeSort.extract 1 (xs.toList.mergeSort.length - 1) := by
309+
simp only [withoutMinMax, maximum, mergeSort_erase_max]
310+
simp only [withoutMin, minimum, mergeSort_erase_min]
311+
-- TODO: simplify the following as soon as the `Array.take/drop` API is merged
312+
simp only [← Array.extract_eq_pop, Array.drop_eq_extract, Array.extract_extract]
313+
simp only [Nat.add_zero, Array.size_mergeSort, Array.size_extract, Std.le_refl,
314+
Nat.min_eq_left, List.length_mergeSort, Array.length_toList]
315+
grind
316+
simp [this]
317+
grind [size_strangeSortArray]
5318

6319
/-!
7320
## Prompt
@@ -52,4 +365,4 @@ def check(candidate):
52365
assert True
53366
54367
```
55-
-/
368+
-/

0 commit comments

Comments
 (0)