-
Notifications
You must be signed in to change notification settings - Fork 1
/
Shared.fs
79 lines (61 loc) · 2.34 KB
/
Shared.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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
///Contains shared utility functions
[<AutoOpen>]
module Shared
///Contains functions for generating random numbers and related values
[<RequireQualifiedAccess>]
module RNG =
open MathNet.Numerics.Random
///Thread safe random number generator
let private random = SystemRandomSource.Default
///Get a value between min and max, inclusive
let get min max =
random.Next (min, (max + 1))
///True if a random value is greater than or equal to a given threshold
let threshold min max value =
(get min max) >= value
///True if a random value is within a given percentile rate (e.g. 0.85 will be true 85% of the time)
let rate value =
let value' = int ((1m - value) * 100m) //Convert 0.85 to a threshold of 25
in threshold 1 100 value'
///True 50% of the time
let flip () = rate 0.5M
///Contains functions for use with the Option<T> type
[<RequireQualifiedAccess>]
module Option =
///Convert from Option<T> to T using the given default value for None
let unwrap defaultValue = function
| Some value -> value
| _ -> defaultValue
///Contains functions for use with the List<T> type
[<RequireQualifiedAccess>]
module List =
///Remove an item by index
let removeIndex index =
let rec f current = function
| [] -> []
| item::items ->
if (current = index) then
f (current + 1) items
else
item :: (f (current + 1) items)
in f 0
///Detach the head from a list as a tuple
let detach items =
List.head items,
List.tail items
///Select a random item from a list
let selectOne list =
let max = (List.length list) - 1
in List.nth list (RNG.get 0 max)
///Select a given number of random items from a list
let rec selectMany count list =
if (count = 0) then
[]
else
let max = (List.length list) - 1
in let index = RNG.get 0 max
let picked = List.nth list index
let remaining = removeIndex index list
picked :: (selectMany (count - 1) remaining)
///Indexes a list, converting from 'a list to (Int32 * 'a) list
let index items = List.mapi (fun index item -> (index, item)) items