-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
import Std.Tactic.Do
import Mathlib
def BubbleSort [LinearOrder α] (A : Array α) := Id.run do
let N := A.size
let mut A := A.toVector
for i in List.range (N - 1) do
for hj : j in List.range (N - i - 1) do
have := List.mem_range.mp hj
if A[j + 1] < A[j] then
A := A.swap j (j + 1)
return A.toArray
def ICan'tBelieveItCanSort [LinearOrder α] (A : Array α) := Id.run do
let N := A.size
let mut A := A.toVector
for hi : i in [:N] do
for hj : j in [:N] do
if A[i] < A[j] then
A := A.swap i j
return A.toArray
#guard let A := #[69, 420, 13, 1, 65536]
ICan'tBelieveItCanSort A = A.qsort
open Std.Do
theorem perm_ICan'tBelieveItCanSort [LinearOrder α] (A : Array α) : ICan'tBelieveItCanSort.{0} A |>.Perm A := by
suffices Multiset.ofList (ICan'tBelieveItCanSort.{0} A).toList = A.toList by
exact { toList := Multiset.coe_eq_coe.mp this }
generalize h : ICan'tBelieveItCanSort A = x
apply Id.of_wp_run_eq h
mvcgen
case inv1 => exact ⇓⟨_, A'⟩ => ⌜Multiset.ofList A.toList = A'.toList⌝
case inv2 => exact ⇓⟨_, A'⟩ => ⌜Multiset.ofList A.toList = A'.toList⌝
all_goals try grind
case vc1.step.isTrue =>
expose_names
simp_all only [Multiset.coe_eq_coe]
exact h_5.trans <| .symm <| Vector.perm_iff_toList_perm.mp <| Vector.swap_perm (by grind) (by grind)
theorem sorted_ICan'tBelieveItCanSort [LinearOrder α] (A : Array α) : ICan'tBelieveItCanSort.{0} A |>.Pairwise (· ≤ ·) := by
generalize h : ICan'tBelieveItCanSort A = x
apply Id.of_wp_run_eq h
mvcgen
case inv1 => exact ⇓⟨xs, A'⟩ => ⌜A'.take xs.pos |>.toArray.Pairwise (· ≤ ·)⌝
case inv2 =>
expose_names
exact ⇓⟨xs, A'⟩ => ⌜(A'.take cur |>.toArray.Pairwise (· ≤ ·)) ∧ ∀ i (_ : i < xs.pos), A'[i]'(by
have : xs.prefix.length + xs.suffix.length = N := by simp [← List.length_append, xs.property]
grind
) ≤ A'[cur]'(by grind)⌝
case vc1.step.isTrue =>
expose_names
simp_all
constructor
· rw [Array.pairwise_iff_getElem] at h_5 ⊢
intro i j hi hj hij
simp
grind
· grind
case vc2.step.isFalse => constructor <;> grind
case vc3.step.pre => grind
case vc4.step.post.success =>
expose_names
simp_all
rw [Array.pairwise_iff_getElem] at h_3 ⊢
grind
case vc5.a.pre => grind
case vc6.a.post.success =>
expose_names
simp_all
rwa [show r.toArray = r.toArray.extract 0 N by grind]
theorem ICanActuallyProveItCanSort [LinearOrder α] (A : Array α) : (ICan'tBelieveItCanSort.{0} A |>.Perm A) ∧ (ICan'tBelieveItCanSort.{0} A |>.Pairwise (· ≤ ·)) :=
⟨perm_ICan'tBelieveItCanSort A, sorted_ICan'tBelieveItCanSort A⟩