25
|
1 |
theory Sort_ops
|
|
2 |
imports Main
|
|
3 |
begin
|
|
4 |
|
|
5 |
ML {*
|
|
6 |
local
|
|
7 |
open Array
|
|
8 |
in
|
|
9 |
|
|
10 |
fun swap i j a = let val ai = sub(a, i);
|
|
11 |
val _ = update(a, i, sub(a, j))
|
|
12 |
val _ = update(a, j, ai)
|
|
13 |
in
|
|
14 |
a
|
|
15 |
end
|
|
16 |
|
|
17 |
fun pre_ops_of a =
|
|
18 |
getM :|-- (fn (l, r, piv, i, j) => let
|
|
19 |
(* val _ = Output.tracing ("("^string_of_int i^","^string_of_int j^")") *)
|
|
20 |
in
|
|
21 |
if (j < i) then (returnM (swap l j a) |-- returnM [(l, j)])
|
|
22 |
else (if (sub(a, i) <= piv andalso i <= r) then (setM (l, r, piv, i + 1, j)
|
|
23 |
|-- pre_ops_of a)
|
|
24 |
else if (sub(a, j) > piv ) then (setM (l, r, piv, i, j - 1) |-- pre_ops_of a)
|
|
25 |
else (pre_ops_of (swap i j a) :|-- (fn ops => returnM ((i,j)::ops))))
|
|
26 |
end
|
|
27 |
)
|
|
28 |
|
|
29 |
fun ops_of i j a =
|
|
30 |
if (j < i) then []
|
|
31 |
else let
|
|
32 |
val piv = sub(a, i)
|
|
33 |
val (ops1, (_, _, _, i', j')) = pre_ops_of a (i, j, piv, i, j) |> normVal
|
|
34 |
val ops2 = ops_of i (j' - 1) a
|
|
35 |
val ops3 = ops_of (j' + 1) j a
|
|
36 |
in
|
|
37 |
ops1 @ ops2 @ ops3
|
|
38 |
end
|
|
39 |
|
|
40 |
fun rem_sdup [] = []
|
|
41 |
| rem_sdup [c] = [c]
|
|
42 |
| rem_sdup ((i, j)::(i', j')::xs) = if ((i = i' andalso j = j') orelse
|
|
43 |
(i = j' andalso j = i')) then rem_sdup (xs)
|
|
44 |
else (i, j)::rem_sdup ((i', j')::xs)
|
|
45 |
fun sexec [] a = a
|
|
46 |
| sexec ((i, j)::ops) a = sexec ops (swap i j a)
|
|
47 |
|
|
48 |
fun swaps_of (l:int list) =
|
|
49 |
ops_of 0 (List.length l - 1) (fromList l) |> rem_sdup
|
|
50 |
|> filter (fn (i, j) => i <> j)
|
|
51 |
end
|
|
52 |
|
|
53 |
*}
|
|
54 |
|
|
55 |
text {* Examples *}
|
|
56 |
|
|
57 |
ML {*
|
|
58 |
val l = [8, 9, 10, 1, 12, 13, 14]
|
|
59 |
val ops = (swaps_of l)
|
|
60 |
val a = (sexec ops (Array.fromList l))
|
|
61 |
val l' = Array.vector a
|
|
62 |
val a = sexec (rev ops) a
|
|
63 |
*}
|
|
64 |
|
|
65 |
end |