11module
22
3- def strange_sort_list : Unit :=
4- ()
3+ def strangeSortArray (xs : Array Int) : Array Int :=
4+ let sorted := xs.toList.mergeSort.toArray
5+ Array.ofFn (n := sorted.size)
6+ (fun i => if i.val % 2 = 0 then sorted[i.val / 2 ] else sorted[sorted.size - 1 - i.val / 2 ])
7+
8+ theorem t {xs : List Int} :
9+ xs.min?.all (· ∈ xs) := by
10+ simp only [Option.all_eq_true_iff_get]
11+ grind
12+
13+ grind_pattern t => xs.min?
14+
15+ def strangeSortListSlow (xs : List Int) : List Int :=
16+ match _ : xs.min? with
17+ | some minimum =>
18+ let xs' := xs.erase minimum
19+ minimum :: (strangeSortListSlow xs'.reverse).reverse
20+ | none => []
21+ termination_by xs.length
22+ decreasing_by grind
23+
24+ theorem strangeSortArray_empty :
25+ strangeSortArray #[] = #[] := by
26+ grind [strangeSortArray, List.mergeSort_nil]
27+
28+ theorem strangeSortArray_singleton :
29+ strangeSortArray #[x] = #[x] := by
30+ ext <;> grind [strangeSortArray, List.mergeSort_singleton, Array.size_ofFn, Array.getElem_ofFn]
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 List.foldl_concat [Max α] {xs : List α} :
65+ (xs.concat x).foldl f init = f (xs.foldl f init) x := by
66+ simp
67+
68+ -- theorem List.max?_concat [Max α] {xs : List α} :
69+ -- (xs.concat x).max? = xs.max?.elim x (fun maximum => max maximum x) := by
70+ -- induction xs
71+ -- sorry
72+
73+ -- theorem List.max?_eq_getLast? [Max α] {xs : List α} (hp : xs.Pairwise (fun a b => max a b = b)) :
74+ -- xs.max? = xs.getLast? := by
75+ -- rw [← List.reverse_reverse (as := xs)]
76+ -- generalize xs.reverse = xs
77+ -- induction xs
78+ -- · simp
79+ -- · rename_i x xs ih
80+ -- simp [List.max?_push, List.getLast?_cons]
81+
82+ theorem List.max_eq_getLast [Max α] {xs : List α} (h) (hp : xs.Pairwise (fun a b => max a b = b)) :
83+ xs.max h = xs.getLast h := by
84+ rw [List.max.eq_def]
85+ split
86+ rename_i x xs _
87+ 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
88+ simp +singlePass only [← List.reverse_reverse (as := xs)]
89+ grind
90+ simp [- pairwise_cons]
91+ intro xs hp
92+ induction xs
93+ · simp
94+ · simp
95+ rename_i ih
96+ rw [ih]
97+ rw [List.reverse_cons, ← List.cons_append, pairwise_append] at hp <;> grind
98+ grind -- what's going on?
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 List.max?_eq_getLast? [Max α] {xs : List α} (hp : xs.Pairwise (fun a b => max a b = b)) :
107+ xs.max? = xs.getLast? := by
108+ cases xs
109+ · simp
110+ · rw [max?_eq_some_max, max_eq_getLast, getLast?_eq_some_getLast]
111+ · simp
112+ · exact hp
113+
114+ theorem Std.min_eq_left_iff [LE α] [Min α] [Std.Refl (α := α) (· ≤ ·)]
115+ [Std.LawfulOrderLeftLeaningMin α] {a b : α} :
116+ min a b = a ↔ a ≤ b := by
117+ by_cases a ≤ b
118+ · grind [Std.LawfulOrderLeftLeaningMin.min_eq_left]
119+ · rename_i h
120+ simp only [Std.LawfulOrderLeftLeaningMin.min_eq_right _ _ h, iff_false, h]
121+ rintro rfl
122+ exact h.elim (Std.Refl.refl _)
123+
124+ theorem Std.max_eq_right_iff [LE α] [Max α] [Std.IsLinearOrder α] [Std.LawfulOrderMax α]
125+ {a b : α} :
126+ max a b = b ↔ a ≤ b := by
127+ open scoped Classical in grind [max_eq_if]
128+
129+ theorem List.getElem_zero_mergeSort {xs : List Int} (h) :
130+ xs.mergeSort[0 ]'h = xs.min (by grind [length_mergeSort]) := by
131+ rw [(xs.mergeSort_perm (· ≤ ·)).symm.min_eq, List.min_eq_head, List.head_eq_getElem]
132+ simp only [Std.min_eq_left_iff]
133+ simpa using xs.pairwise_mergeSort (by grind) (by grind) (le := (· ≤ ·))
134+
135+ theorem List.getElem_length_sub_one_mergeSort {xs : List Int} (h) :
136+ xs.mergeSort[xs.length - 1 ]'h = xs.max (by grind [length_mergeSort]) := by
137+ rw [(xs.mergeSort_perm (· ≤ ·)).symm.max_eq, List.max_eq_getLast, List.getLast_eq_getElem]
138+ · simp [List.length_mergeSort]
139+ · simp only [Std.max_eq_right_iff]
140+ simpa using xs.pairwise_mergeSort (by grind) (by grind) (le := (· ≤ ·))
141+
142+ theorem List.max_erase_le_max {xs : List Int} (h) :
143+ (xs.erase x).max h ≤ xs.max (by grind) := by
144+ simp only [List.max_le_iff]
145+ intro b hb
146+ apply List.le_max_of_mem
147+ exact List.mem_of_mem_erase hb
148+
149+ theorem Array.max_erase_le_max {xs : Array Int} {h} :
150+ (xs.erase x).max h ≤ xs.max (by grind) := by
151+ simp only [Array.max_le_iff]
152+ intro b hb
153+ apply Array.le_max_of_mem
154+ exact Array.mem_of_mem_erase hb
155+
156+ theorem List.count_dropLast [BEq α] {xs : List α} {a : α} :
157+ xs.dropLast.count a = xs.count a - if xs.getLast? == some a then 1 else 0 := by
158+ rw [← List.reverse_reverse (as := xs)]
159+ generalize xs.reverse = xs
160+ rw [dropLast_reverse, count_reverse, count_tail, getLast?_reverse, count_reverse]
161+
162+ theorem Array.count_pop [BEq α] {xs : Array α} {a : α} :
163+ xs.pop.count a = xs.count a - if xs.back? == some a then 1 else 0 := by
164+ rw [← count_toList, toList_pop, List.count_dropLast, getLast?_toList, count_toList]
165+
166+ theorem bla {xs : Array Int} {h} :
167+ (xs.erase (xs.max h)).Perm xs.toList.mergeSort.toArray.pop := by
168+ simp only [Array.perm_iff_toList_perm]
169+ simp [List.perm_iff_count, Array.count_toList, - List.pop_toArray, - Array.toList_pop]
170+ intro a
171+ rw [Array.count_erase]
172+ have h_mem : xs.max h ∈ xs := by grind
173+ rw [Array.count_pop, List.count_toArray, List.count_toArray, (List.mergeSort_perm _ _).count_eq,
174+ List.back?_toArray, ← List.max?_eq_getLast?, (List.mergeSort_perm _ _).max?_eq, Array.max?_toList,
175+ Array.max?_eq_some_max]
176+ · simp
177+ · grind
178+ · simp only [Std.max_eq_right_iff]
179+ simpa using List.pairwise_mergeSort (α := Int) (le := (· ≤ ·)) (by grind) (by grind) _
180+
181+ theorem bla' {xs : Array Int} {h} :
182+ (xs.erase (xs.max h)).toList.mergeSort = xs.toList.mergeSort.dropLast := by
183+ apply List.Perm.eq_of_pairwise (le := (· ≤ ·))
184+ · grind
185+ · simpa using List.pairwise_mergeSort (α := Int) (le := (· ≤ ·)) (by grind) (by grind) _
186+ · simp only [List.dropLast_eq_take]
187+ apply List.Pairwise.take
188+ simpa using List.pairwise_mergeSort (α := Int) (le := (· ≤ ·)) (by grind) (by grind) _
189+ · refine List.Perm.trans (List.mergeSort_perm _ _) ?_
190+ rw [← Array.perm_iff_toList_perm]
191+ apply bla
192+
193+ theorem blub' {xs : Array Int} {h} :
194+ (xs.erase (xs.min h)).toList.mergeSort = xs.toList.mergeSort.drop 1 := by
195+ apply List.Perm.eq_of_pairwise (le := (· ≤ ·))
196+ · grind
197+ · simpa using List.pairwise_mergeSort (α := Int) (le := (· ≤ ·)) (by grind) (by grind) _
198+ · apply List.Pairwise.drop
199+ simpa using List.pairwise_mergeSort (α := Int) (le := (· ≤ ·)) (by grind) (by grind) _
200+ · refine List.Perm.trans (List.mergeSort_perm _ _) ?_
201+ rw [← Array.perm_iff_toList_perm]
202+ simp only [Array.perm_iff_toList_perm]
203+ simp [List.perm_iff_count, Array.count_toList, - List.pop_toArray, - Array.toList_pop]
204+ intro a
205+ rw [Array.count_erase]
206+ have h_mem : xs.max h ∈ xs := by grind
207+ rw [List.count_tail, List.count_toArray, (List.mergeSort_perm _ _).count_eq,
208+ ← List.min?_eq_head?, (List.mergeSort_perm _ _).min?_eq, Array.min?_toList,
209+ Array.min?_eq_some_min]
210+ · simp
211+ · grind
212+ · simp only [Std.min_eq_left_iff]
213+ simpa using List.pairwise_mergeSort (α := Int) (le := (· ≤ ·)) (by grind) (by grind) _
214+
215+ theorem size_strangeSortArray {xs : Array Int} :
216+ (strangeSortArray xs).size = xs.size := by
217+ simp [strangeSortArray]
218+
219+ theorem strangeSortArray_of_two_le_size (h : 2 ≤ xs.size) :
220+ let minimum := xs.min (by grind)
221+ let withoutMin := xs.erase minimum
222+ let maximum := withoutMin.max (by grind)
223+ let withoutMinMax := withoutMin.erase maximum
224+ strangeSortArray xs = #[minimum, maximum] ++ strangeSortArray withoutMinMax := by
225+ intro minimum withoutMin maximum withoutMinMax
226+ ext
227+ · simp [strangeSortArray]
228+ grind
229+ · rename_i i h₁ h₂
230+ simp [strangeSortArray]
231+ match i with
232+ | 0 => grind [List.getElem_zero_mergeSort]
233+ | 1 =>
234+ simp [← Array.length_toList, List.getElem_length_sub_one_mergeSort, maximum, withoutMin]
235+ rw [Array.max_eq_iff]
236+ constructor
237+ · grind [Array.mem_of_mem_erase]
238+ · intro b hb
239+ by_cases hb' : b = minimum
240+ · cases hb'
241+ simp only [minimum]
242+ apply Array.min_le_of_mem
243+ exact Array.mem_of_mem_erase (Array.max_mem _)
244+ · apply Array.le_max_of_mem
245+ rwa [Array.mem_erase_of_ne]
246+ assumption
247+ | j + 2 =>
248+ have : withoutMinMax.toList.mergeSort = xs.toList.mergeSort.extract 1 (xs.toList.mergeSort.length - 1 ) := by
249+ simp only [withoutMinMax, maximum, bla']
250+ simp only [withoutMin, minimum, blub']
251+ simp only [List.extract_eq_take_drop, List.dropLast_eq_take]
252+ grind
253+ simp [this]
254+ grind [size_strangeSortArray]
5255
6256/-!
7257## Prompt
@@ -52,4 +302,4 @@ def check(candidate):
52302 assert True
53303
54304```
55- -/
305+ -/
0 commit comments