forked from fsprojects/fantomas
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mergesort.fs
61 lines (53 loc) · 1.62 KB
/
mergesort.fs
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
/// The program is from http://codereview.stackexchange.com/q/12643
module Mergesort
open System
open System.Windows
open System.Collections.Generic
let shuffle (l : 'a array) =
let ileft = LinkedList<int>(seq { 0..(l.Length - 1) })
let rec pick (ar : 'a array) r =
match ileft.Count with
| 0 -> r
| n ->
let ik = ileft |> Seq.nth (rnd.Next(n))
ileft.Remove(ik) |> ignore
pick ar (ar.[ik] :: r)
pick l []
let rec merge (ar1 : 'a array) (ar2 : 'a array) =
let rec index (islastfromAr1, ilast, jlast) =
seq {
let inext, jnext = ilast + 1, jlast + 1
match inext < ar1.Length, jnext < ar2.Length with
| true, true ->
let indexnext =
if ar1.[inext] < ar2.[jnext] then (true, inext, jlast)
else (false, ilast, jnext)
yield Some(indexnext)
yield! index indexnext
| false, true ->
let indexnext = (false, ilast, jnext)
yield Some(indexnext)
yield! index indexnext
| true, false ->
let indexnext = (true, inext, jlast)
yield Some(indexnext)
yield! index indexnext
| false, false -> yield None
}
let mergeindex = index (false, -1, -1)
[ for (formar1, i, j) in mergeindex |> Seq.choose (id) ->
if formar1 then ar1.[i]
else ar2.[j] ]
and mergesort =
function
| [||] -> [||]
| [| a |] -> [| a |]
| ar ->
let ar1 = ar.[0..ar.Length / 2 - 1]
let ar2 = ar.[ar.Length / 2..ar.Length - 1]
merge (mergesort ar1) (mergesort ar2) |> List.toArray
let testval =
([| 1..100 |]
|> shuffle
|> List.toArray)
let test4 = mergesort testval